"""
Management command to generate AI assistant context files for a djust project.

Generates project-aware documentation files for AI coding assistants:
- CLAUDE.md for Claude Code
- .cursorrules for Cursor
- .github/copilot-instructions.md for GitHub Copilot

Each file includes: framework directives, project views with handlers,
template bindings, and available components.

Usage:
    python manage.py djust_ai_context --format claude    # -> CLAUDE.md
    python manage.py djust_ai_context --format cursor    # -> .cursorrules
    python manage.py djust_ai_context --format copilot   # -> .github/copilot-instructions.md
    python manage.py djust_ai_context --format claude --output /path/to/file
"""

import os

from django.core.management.base import BaseCommand


class Command(BaseCommand):
    help = "Generate AI assistant context files for this djust project"

    def add_arguments(self, parser):
        parser.add_argument(
            "--format",
            type=str,
            choices=["claude", "cursor", "copilot"],
            default="claude",
            help="Output format: claude (CLAUDE.md), cursor (.cursorrules), copilot (.github/copilot-instructions.md)",
        )
        parser.add_argument(
            "--output",
            type=str,
            default=None,
            help="Custom output path. Defaults to format-specific location.",
        )
        parser.add_argument(
            "--print",
            action="store_true",
            dest="print_stdout",
            help="Print to stdout instead of writing to file",
        )

    def handle(self, *args, **options):
        from djust.schema import get_framework_schema, get_project_schema

        fmt = options["format"]
        output_path = options.get("output")
        to_stdout = options.get("print_stdout", False)

        framework = get_framework_schema()
        project = get_project_schema()

        content = _generate_content(framework, project, fmt)

        if to_stdout:
            self.stdout.write(content)
            return

        if output_path is None:
            output_path = _default_path(fmt)

        # Ensure parent directory exists
        parent = os.path.dirname(output_path)
        if parent and not os.path.exists(parent):
            os.makedirs(parent, exist_ok=True)

        with open(output_path, "w") as f:
            f.write(content)

        self.stdout.write(self.style.SUCCESS("Wrote %s" % output_path))


def _default_path(fmt: str) -> str:
    """Return the default output path for the given format."""
    if fmt == "claude":
        return "CLAUDE.md"
    elif fmt == "cursor":
        return ".cursorrules"
    elif fmt == "copilot":
        return os.path.join(".github", "copilot-instructions.md")
    return "CLAUDE.md"


def _generate_content(framework: dict, project: dict, fmt: str) -> str:
    """Generate the full AI context document."""
    sections = []

    # Header
    if fmt == "claude":
        sections.append("# CLAUDE.md — djust Project Context\n")
        sections.append("Auto-generated by `python manage.py djust_ai_context --format claude`.\n")
    elif fmt == "cursor":
        sections.append("# .cursorrules — djust Project Context\n")
        sections.append("Auto-generated by `python manage.py djust_ai_context --format cursor`.\n")
    elif fmt == "copilot":
        sections.append("# Copilot Instructions — djust Project Context\n")
        sections.append("Auto-generated by `python manage.py djust_ai_context --format copilot`.\n")

    sections.append(
        "This project uses the **djust** framework (v%s) — "
        "a hybrid Python/Rust framework bringing Phoenix LiveView-style "
        "reactive server-side rendering to Django.\n" % framework.get("version", "?")
    )

    # Framework quick reference
    sections.append(_section_directives(framework))
    sections.append(_section_lifecycle(framework))
    sections.append(_section_decorators(framework))
    sections.append(_section_conventions(framework))

    # Project-specific
    if project.get("views") or project.get("components"):
        sections.append(_section_project_views(project))

    if project.get("routes"):
        sections.append(_section_routes(project))

    return "\n".join(sections)


def _section_directives(framework: dict) -> str:
    """Generate the template directives reference section."""
    lines = ["## Template Directives\n"]

    by_category = {}
    for d in framework.get("directives", []):
        cat = d.get("category", "other")
        by_category.setdefault(cat, []).append(d)

    category_order = [
        "event",
        "binding",
        "dom",
        "loading",
        "client",
        "modifier",
        "hooks",
        "navigation",
        "streaming",
        "upload",
    ]

    for cat in category_order:
        directives = by_category.get(cat, [])
        if not directives:
            continue
        lines.append("### %s\n" % cat.title())
        for d in directives:
            lines.append("- **`%s`** = `%s`" % (d["name"], d.get("value", "")))
            lines.append("  %s" % d.get("description", ""))
            if d.get("modifiers"):
                lines.append("  Modifiers: %s" % ", ".join(".%s" % m for m in d["modifiers"]))
            if d.get("example"):
                lines.append("  ```html\n  %s\n  ```" % d["example"])
            lines.append("")

    # Data attribute types
    lines.append("### Data Attribute Type Coercion\n")
    for suffix, desc in framework.get("data_attribute_types", {}).items():
        lines.append("- `data-name:%s` — %s" % (suffix, desc))
    lines.append("")

    return "\n".join(lines)


def _section_lifecycle(framework: dict) -> str:
    """Generate the lifecycle methods section."""
    lines = ["## Lifecycle Methods\n"]

    for method in framework.get("lifecycle_methods", []):
        lines.append("- **`%s`** — %s" % (method["name"], method["description"]))
        lines.append("  ```python\n  %s\n  ```" % method["signature"])

    lines.append("")

    # Navigation methods
    lines.append("### Server-Side Navigation\n")
    for m in framework.get("navigation_methods", []):
        lines.append("- `%s` — %s" % (m["signature"], m["description"]))

    # Stream methods
    lines.append("\n### Streams API\n")
    for m in framework.get("stream_methods", []):
        lines.append("- `%s` — %s" % (m["signature"], m["description"]))

    # Push events
    lines.append("\n### Push Events\n")
    for m in framework.get("push_event_methods", []):
        lines.append("- `%s` — %s" % (m["signature"], m["description"]))

    lines.append("")
    return "\n".join(lines)


def _section_decorators(framework: dict) -> str:
    """Generate the decorators section."""
    lines = ["## Decorators\n"]

    for dec in framework.get("decorators", []):
        lines.append("### `%s`\n" % dec["name"])
        lines.append("%s\n" % dec["description"])
        lines.append("`%s`\n" % dec["import"])
        if dec.get("params"):
            lines.append("Parameters:")
            for pname, pdesc in dec["params"].items():
                lines.append("- `%s`: %s" % (pname, pdesc))
            lines.append("")
        if dec.get("usage"):
            lines.append("```python")
            lines.append(dec["usage"][0])
            lines.append("```\n")

    return "\n".join(lines)


def _section_conventions(framework: dict) -> str:
    """Generate the conventions section."""
    lines = ["## Conventions\n"]

    for key, conv in framework.get("conventions", {}).items():
        lines.append("### %s\n" % key.replace("_", " ").title())
        lines.append("%s\n" % conv["description"])
        if "examples" in conv:
            for example, desc in conv["examples"].items():
                lines.append("- `%s` — %s" % (example, desc))
            lines.append("")

    return "\n".join(lines)


def _section_project_views(project: dict) -> str:
    """Generate the project views and components section."""
    lines = ["## Project Views\n"]

    for view in project.get("views", []):
        lines.append("### `%s`\n" % view["class"])
        if view.get("template"):
            lines.append("Template: `%s`" % view["template"])
        if view.get("mixins"):
            lines.append("Mixins: %s" % ", ".join(view["mixins"]))
        if view.get("auth"):
            auth_parts = []
            if view["auth"].get("login_required"):
                auth_parts.append("login_required")
            if view["auth"].get("permission_required"):
                auth_parts.append("permission: %s" % ", ".join(view["auth"]["permission_required"]))
            if auth_parts:
                lines.append("Auth: %s" % ", ".join(auth_parts))

        # Handlers
        if view.get("handlers"):
            lines.append("\nHandlers:")
            for h in view["handlers"]:
                params_str = ", ".join(
                    "%s: %s" % (p["name"], p.get("type", "Any")) for p in h.get("params", [])
                )
                dec_tags = []
                for dec_name, dec_val in h.get("decorators", {}).items():
                    if dec_val is True:
                        dec_tags.append("@%s" % dec_name)
                    else:
                        dec_tags.append("@%s" % dec_name)
                dec_str = " ".join(dec_tags)
                line = "- `%s(%s)`" % (h["name"], params_str)
                if dec_str:
                    line += "  %s" % dec_str
                if h.get("description"):
                    desc = h["description"].strip().split("\n")[0]
                    line += " — %s" % desc
                lines.append(line)

        # Exposed state
        if view.get("exposed_state"):
            lines.append(
                "\nTemplate variables: %s"
                % ", ".join("`%s`" % k for k in sorted(view["exposed_state"].keys()))
            )

        lines.append("")

    # Components
    if project.get("components"):
        lines.append("## Project Components\n")
        for comp in project["components"]:
            lines.append("### `%s`\n" % comp["class"])
            if comp.get("template"):
                lines.append("Template: `%s`" % comp["template"])
            if comp.get("handlers"):
                lines.append("Handlers: %s" % ", ".join(h["name"] for h in comp["handlers"]))
            lines.append("")

    return "\n".join(lines)


def _section_routes(project: dict) -> str:
    """Generate the URL routes section."""
    lines = ["## URL Routes\n"]

    for route in project.get("routes", []):
        name = route.get("name", "")
        name_str = " (name='%s')" % name if name else ""
        lines.append("- `%s` -> `%s`%s" % (route["pattern"], route["view"], name_str))

    lines.append("")
    return "\n".join(lines)
