#!/usr/bin/env python3
"""
API Reference Builder

Generates markdown API documentation from code analysis results.
Supports Python, JavaScript/TypeScript, and C++.

Output Format:
- One .md file per analyzed source file
- Organized by: Classes → Methods, then standalone Functions
- Includes: Signatures, parameters, return types, docstrings

Usage:
    from skill_seekers.cli.api_reference_builder import APIReferenceBuilder

    builder = APIReferenceBuilder(code_analysis_results)
    builder.build_reference(output_dir)
"""

import json
from pathlib import Path
from typing import Any


class APIReferenceBuilder:
    """
    Builds markdown API reference from code analysis results.

    Processes code analysis data and generates well-formatted markdown
    documentation for each analyzed source file.
    """

    def __init__(self, code_analysis: dict[str, Any]):
        """
        Initialize builder with code analysis results.

        Args:
            code_analysis: Dictionary containing analyzed files and their code structures.
                          Expected format: {'files': [{'file': 'path', 'classes': [...], 'functions': [...]}]}
        """
        self.code_analysis = code_analysis
        self.files_data = code_analysis.get("files", [])

    def build_reference(self, output_dir: Path) -> dict[str, Path]:
        """
        Generate markdown files for each analyzed source file.

        Args:
            output_dir: Directory to save generated markdown files

        Returns:
            Dictionary mapping source file paths to generated markdown file paths
        """
        output_dir = Path(output_dir)
        output_dir.mkdir(parents=True, exist_ok=True)

        generated_files = {}

        for file_data in self.files_data:
            source_file = file_data.get("file", "unknown")
            language = file_data.get("language", "Unknown")

            # Skip files with no analysis
            if not file_data.get("classes") and not file_data.get("functions"):
                continue

            # Generate markdown content
            markdown_content = self._generate_file_reference(file_data, source_file, language)

            # Determine output filename
            output_filename = self._get_output_filename(source_file)
            output_path = output_dir / output_filename

            # Write markdown file
            output_path.write_text(markdown_content, encoding="utf-8")
            generated_files[source_file] = output_path

        return generated_files

    def _get_output_filename(self, source_file: str) -> str:
        """
        Generate output filename from source file path.

        Args:
            source_file: Path to source file

        Returns:
            Safe filename for markdown output
        """
        # Get base filename
        basename = Path(source_file).name

        # Replace extension with .md
        name_without_ext = basename.rsplit(".", 1)[0] if "." in basename else basename
        return f"{name_without_ext}.md"

    def _generate_file_reference(
        self, file_data: dict[str, Any], source_file: str, language: str
    ) -> str:
        """
        Generate complete markdown reference for a single file.

        Args:
            file_data: Analysis data for the file
            source_file: Path to source file
            language: Programming language

        Returns:
            Complete markdown content
        """
        lines = []

        # Header
        filename = Path(source_file).name
        lines.append(f"# API Reference: {filename}\n")
        lines.append(f"**Language**: {language}\n")
        lines.append(f"**Source**: `{source_file}`\n")
        lines.append("---\n")

        # Classes section
        classes = file_data.get("classes", [])
        if classes:
            lines.append("## Classes\n")
            for cls in classes:
                lines.append(self._format_class(cls))
                lines.append("\n")

        # Functions section
        functions = file_data.get("functions", [])
        if functions:
            lines.append("## Functions\n")
            for func in functions:
                lines.append(self._format_function(func))
                lines.append("\n")

        return "\n".join(lines)

    def _format_class(self, class_sig: dict[str, Any]) -> str:
        """
        Format class signature as markdown.

        Args:
            class_sig: Class signature dictionary

        Returns:
            Formatted markdown for class
        """
        lines = []

        # Class name
        class_name = class_sig.get("name", "Unknown")
        lines.append(f"### {class_name}\n")

        # Docstring
        docstring = class_sig.get("docstring")
        if docstring:
            lines.append(f"{docstring}\n")

        # Inheritance
        base_classes = class_sig.get("base_classes", [])
        if base_classes:
            bases_str = ", ".join(base_classes)
            lines.append(f"**Inherits from**: {bases_str}\n")
        else:
            lines.append("**Inherits from**: (none)\n")

        # Methods
        methods = class_sig.get("methods", [])
        if methods:
            lines.append("#### Methods\n")
            for method in methods:
                lines.append(self._format_method(method))
                lines.append("")

        return "\n".join(lines)

    def _format_method(self, method_sig: dict[str, Any]) -> str:
        """
        Format method signature as markdown.

        Args:
            method_sig: Method signature dictionary

        Returns:
            Formatted markdown for method
        """
        lines = []

        # Method signature
        signature = self._build_signature(method_sig)
        lines.append(f"##### {signature}\n")

        # Docstring
        docstring = method_sig.get("docstring")
        if docstring:
            lines.append(f"{docstring}\n")

        # Decorators
        decorators = method_sig.get("decorators", [])
        if decorators:
            dec_str = ", ".join(f"`@{d}`" for d in decorators)
            lines.append(f"**Decorators**: {dec_str}\n")

        # Parameters table
        params = method_sig.get("parameters", [])
        if params:
            lines.append(self._format_parameters(params))
            lines.append("")

        # Return type
        return_type = method_sig.get("return_type")
        if return_type:
            lines.append(f"**Returns**: `{return_type}`\n")

        return "\n".join(lines)

    def _format_function(self, func_sig: dict[str, Any]) -> str:
        """
        Format function signature as markdown.

        Args:
            func_sig: Function signature dictionary

        Returns:
            Formatted markdown for function
        """
        lines = []

        # Function signature
        signature = self._build_signature(func_sig)
        lines.append(f"### {signature}\n")

        # Async indicator
        if func_sig.get("is_async"):
            lines.append("**Async function**\n")

        # Docstring
        docstring = func_sig.get("docstring")
        if docstring:
            lines.append(f"{docstring}\n")

        # Parameters table
        params = func_sig.get("parameters", [])
        if params:
            lines.append(self._format_parameters(params))
            lines.append("")

        # Return type
        return_type = func_sig.get("return_type")
        if return_type:
            lines.append(f"**Returns**: `{return_type}`\n")
        else:
            lines.append("**Returns**: (none)\n")

        return "\n".join(lines)

    def _build_signature(self, sig: dict[str, Any]) -> str:
        """
        Build function/method signature string.

        Args:
            sig: Signature dictionary

        Returns:
            Formatted signature string
        """
        name = sig.get("name", "unknown")
        params = sig.get("parameters", [])
        return_type = sig.get("return_type")

        # Build parameter list
        param_strs = []
        for param in params:
            param_str = param.get("name", "")

            # Add type hint if available
            type_hint = param.get("type_hint")
            if type_hint:
                param_str += f": {type_hint}"

            # Add default value if available
            default = param.get("default")
            if default:
                param_str += f" = {default}"

            param_strs.append(param_str)

        params_str = ", ".join(param_strs)

        # Build full signature
        if return_type:
            return f"{name}({params_str}) → {return_type}"
        else:
            return f"{name}({params_str})"

    def _format_parameters(self, params: list[dict]) -> str:
        """
        Format parameter list as markdown table.

        Args:
            params: List of parameter dictionaries

        Returns:
            Formatted markdown table
        """
        if not params:
            return ""

        lines = []
        lines.append("**Parameters**:")
        lines.append("")
        lines.append("| Name | Type | Default | Description |")
        lines.append("|------|------|---------|-------------|")

        for param in params:
            name = param.get("name", "-")
            type_hint = param.get("type_hint", "-")
            default = param.get("default")

            # Show "-" for parameters without defaults
            default_str = default if default is not None else "-"

            # For description, use empty for now (would need JSDoc/docstring parsing)
            description = "-"

            lines.append(f"| {name} | {type_hint} | {default_str} | {description} |")

        return "\n".join(lines)


def main():
    """
    Command-line interface for API reference generation.

    Reads code analysis JSON and generates markdown API documentation.
    """
    import argparse

    parser = argparse.ArgumentParser(
        description="Generate API reference from code analysis results"
    )

    parser.add_argument("input_file", help="Code analysis JSON file")
    parser.add_argument("output_dir", help="Output directory for markdown files")

    args = parser.parse_args()

    # Read code analysis
    input_path = Path(args.input_file)
    if not input_path.exists():
        print(f"Error: Input file not found: {input_path}")
        return 1

    with open(input_path, encoding="utf-8") as f:
        code_analysis = json.load(f)

    # Build API reference
    builder = APIReferenceBuilder(code_analysis)
    generated_files = builder.build_reference(Path(args.output_dir))

    # Report results
    print(f"✅ Generated {len(generated_files)} API reference files")
    print(f"📁 Output directory: {args.output_dir}")
    for source, output in generated_files.items():
        print(f"  • {output.name} (from {Path(source).name})")

    return 0


if __name__ == "__main__":
    import sys

    sys.exit(main())
