"""
Management command to generate createOS tasks from SST specifications.

Usage:
    # Preview task generation (dry-run)
    python manage.py spec_generate_tasks user_flows/auth/signup.yaml --dry-run

    # Generate tasks with goal tests
    python manage.py spec_generate_tasks user_flows/auth/signup.yaml --with-goal-tests

    # Link to existing epic/story
    python manage.py spec_generate_tasks user_flows/auth/signup.yaml --epic <id>
"""

from pathlib import Path
from typing import Any

import yaml
from django.core.management.base import BaseCommand, CommandError

SST_ROOT = Path(__file__).parents[2] / "definitions"


class Command(BaseCommand):
    """Generate createOS tasks from SST specification files."""

    help = "Generate prelim task and tests from SST spec"

    def add_arguments(self, parser: Any) -> None:
        parser.add_argument(
            "spec_path",
            type=str,
            help="Path to spec YAML relative to definitions/ (e.g., user_flows/auth/signup.yaml)",
        )
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="Preview what would be created without making changes",
        )
        parser.add_argument(
            "--with-goal-tests",
            action="store_true",
            help="Generate Layer 2 goal achievement tests",
        )
        parser.add_argument(
            "--epic",
            type=str,
            help="Link generated tasks to this epic ID",
        )
        parser.add_argument(
            "--story",
            type=str,
            help="Link generated tasks to this story ID",
        )

    def handle(self, *args: Any, **options: Any) -> None:
        spec_path_str = options["spec_path"]
        dry_run = options.get("dry_run", False)
        with_goal_tests = options.get("with_goal_tests", False)
        epic_id = options.get("epic")
        story_id = options.get("story")

        # Resolve spec path
        spec_path = SST_ROOT / spec_path_str
        if not spec_path.exists():
            raise CommandError(f"Spec not found: {spec_path}")

        # Load spec
        try:
            spec = yaml.safe_load(spec_path.read_text())
        except yaml.YAMLError as e:
            raise CommandError(f"Invalid YAML: {e}")

        meta = spec.get("_meta", {})
        component = meta.get("component", spec_path.stem)
        version = meta.get("version", "1.0.0")

        self.stdout.write(f"\nSpec: {spec_path_str}")
        self.stdout.write(f"Component: {component}")
        self.stdout.write(f"Version: {version}")
        self.stdout.write("-" * 50)

        if dry_run:
            self.stdout.write(self.style.WARNING("\n[DRY RUN] Would create:"))

        # Generate prelim task
        prelim_title = f"Research: {component} implementation"
        self._output_task(prelim_title, "prelim", dry_run, epic_id, story_id)

        # Generate tasks from user stories if present
        user_stories = spec.get("user_stories", [])
        for story in user_stories:
            story_title = story.get("title", story.get("name", "Untitled"))
            self._output_task(f"Story: {story_title}", "story", dry_run, epic_id, story_id)

            for task in story.get("tasks", []):
                task_title = task.get("title", task.get("name", "Untitled"))
                self._output_task(f"  Task: {task_title}", "task", dry_run, epic_id, story_id)

        # Generate contract tests (Layer 1)
        steps = spec.get("steps", spec.get("routes", spec.get("endpoints", [])))
        if steps:
            self._output_task(f"Tests: Contract tests for {component}", "test", dry_run, epic_id, story_id)
            if dry_run and options.get("verbosity", 1) > 1:
                self._preview_contract_tests(steps)

        # Generate goal tests (Layer 2)
        if with_goal_tests:
            acceptance = spec.get("acceptance_criteria", spec.get("goals", []))
            if acceptance:
                self._output_task(f"Tests: Goal tests for {component}", "goal-test", dry_run, epic_id, story_id)

        if not dry_run:
            self.stdout.write(self.style.WARNING("\nTODO: Implement createOS API integration"))
            self.stdout.write("Tasks would be created via: POST /api/createos/tasks/")

    def _output_task(
        self,
        title: str,
        task_type: str,
        dry_run: bool,
        epic_id: str | None,
        story_id: str | None,
    ) -> None:
        """Output a task to be created."""
        prefix = "  " if task_type == "task" else ""
        if dry_run:
            self.stdout.write(f"{prefix}- {title}")
        else:
            # TODO: Call createOS API
            self.stdout.write(f"{prefix}+ {title}")

    def _preview_contract_tests(self, steps: list[dict[str, Any]]) -> None:
        """Preview contract tests that would be generated."""
        self.stdout.write("    Contract tests preview:")
        for step in steps[:5]:  # Show first 5
            name = step.get("name", step.get("route", step.get("endpoint", "unknown")))
            method = step.get("method", "GET")
            expected = step.get("expected_status", step.get("status", 200))
            self.stdout.write(f"      test_{name}_{method.lower()}_returns_{expected}()")
        if len(steps) > 5:
            self.stdout.write(f"      ... and {len(steps) - 5} more")
