import ast
import sys


def extract_symbols(file_path):
    # Mapping from AST node types to their corresponding names
    map_node_to_name = {"ClassDef": "class", "FunctionDef": "def"}

    # Read the content of the specified file
    with open(file_path, "r") as file:
        code = file.read()

    # Parse the code into an abstract syntax tree (AST)
    tree = ast.parse(code)
    symbols = []

    # Recursive function to traverse the AST and extract class and function names
    def parse_node(node, indent=""):
        result = ""

        # Check if the node is a ClassDef or FunctionDef
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
            # Format the line number with leading spaces
            lineno = f"{node.lineno: >4}"
            # Create a string representation of the node
            result += f"{lineno} {indent}{map_node_to_name[type(node).__name__]} {node.name}\n"

        # If the node is a ClassDef, recursively process its body
        if isinstance(node, ast.ClassDef):
            for subnode in node.body:
                result += parse_node(subnode, indent + "    ")

        # If the node is a FunctionDef or AsyncFunctionDef, recursively process its body
        elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
            for subnode in node.body:
                result += parse_node(subnode, indent + "        ")

        return result

    # Process each top-level node in the AST
    for node in tree.body:
        symbols.append(parse_node(node))

    return symbols


if __name__ == "__main__":
    # Check if the correct number of command-line arguments is provided
    if len(sys.argv) != 2:
        print("Usage: python extract_symbols.py <file_path>")
        sys.exit(1)

    # Get the file path from the command-line argument
    file_path = sys.argv[1]

    # Extract symbols from the specified file
    result = extract_symbols(file_path)

    # Filter out empty lines and print the output
    output = "\n".join(line for line in result if line.strip())

    if len(output) > 0:
        print(output)
    else:
        print("No classes or functions found")
