"""
Management command to validate SST specs against staging/production.

Usage:
    # Validate against staging
    python manage.py spec_validate_production user_flows/auth/signup.yaml --staging

    # Validate against production
    python manage.py spec_validate_production routes.yaml

    # Create incident on failure
    python manage.py spec_validate_production routes.yaml --create-incident
"""

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):
    """Run smoke tests against staging or production based on SST spec."""

    help = "Run smoke tests against staging or production"

    def add_arguments(self, parser: Any) -> None:
        parser.add_argument(
            "spec_path",
            type=str,
            help="Path to spec YAML relative to definitions/",
        )
        parser.add_argument(
            "--staging",
            action="store_true",
            help="Run against staging environment",
        )
        parser.add_argument(
            "--create-incident",
            action="store_true",
            help="Create incident ticket on validation failure",
        )
        parser.add_argument(
            "--base-url",
            type=str,
            help="Override base URL for tests",
        )

    def handle(self, *args: Any, **options: Any) -> None:
        spec_path_str = options["spec_path"]
        is_staging = options.get("staging", False)
        create_incident = options.get("create_incident", False)
        base_url = options.get("base_url")

        # 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)

        env = "staging" if is_staging else "production"
        self.stdout.write(f"\nValidating {component} against {env}")
        self.stdout.write("=" * 50)

        # Determine base URL
        if not base_url:
            base_url = self._get_base_url(is_staging, meta)

        self.stdout.write(f"Base URL: {base_url}")
        self.stdout.write("")

        # Extract testable endpoints
        endpoints = self._extract_endpoints(spec)
        if not endpoints:
            self.stdout.write(self.style.WARNING("No testable endpoints found in spec"))
            return

        # Run smoke tests
        passed = 0
        failed = 0
        failures: list[dict[str, Any]] = []

        for endpoint in endpoints:
            result = self._test_endpoint(endpoint, base_url)
            if result["success"]:
                passed += 1
                self.stdout.write(self.style.SUCCESS(f"  ✓ {endpoint['name']}"))
            else:
                failed += 1
                self.stdout.write(self.style.ERROR(f"  ✗ {endpoint['name']}: {result['error']}"))
                failures.append({**endpoint, "error": result["error"]})

        # Summary
        self.stdout.write("")
        self.stdout.write("=" * 50)
        total = passed + failed
        if failed == 0:
            self.stdout.write(self.style.SUCCESS(f"✓ All {total} tests passed"))
        else:
            self.stdout.write(self.style.ERROR(f"✗ {failed}/{total} tests failed"))

            if create_incident and failures:
                self._create_incident(component, env, failures)

    def _get_base_url(self, is_staging: bool, meta: dict[str, Any]) -> str:
        """Determine base URL from environment or meta."""
        if is_staging:
            return meta.get("staging_url", "https://staging.lightwave.media")
        return meta.get("production_url", "https://lightwave.media")

    def _extract_endpoints(self, spec: dict[str, Any]) -> list[dict[str, Any]]:
        """Extract testable endpoints from spec."""
        endpoints = []

        # Check routes
        for route in spec.get("routes", []):
            endpoints.append(
                {
                    "name": route.get("name", route.get("path", "unknown")),
                    "method": route.get("method", "GET"),
                    "path": route.get("path", route.get("route", "/")),
                    "expected_status": route.get("expected_status", 200),
                }
            )

        # Check steps in user flows
        for step in spec.get("steps", []):
            if step.get("route") or step.get("endpoint"):
                endpoints.append(
                    {
                        "name": step.get("name", "step"),
                        "method": step.get("method", "GET"),
                        "path": step.get("route", step.get("endpoint", "/")),
                        "expected_status": step.get("expected_status", 200),
                    }
                )

        # Check endpoints directly
        for endpoint in spec.get("endpoints", []):
            endpoints.append(
                {
                    "name": endpoint.get("name", endpoint.get("path", "unknown")),
                    "method": endpoint.get("method", "GET"),
                    "path": endpoint.get("path", "/"),
                    "expected_status": endpoint.get("expected_status", 200),
                }
            )

        return endpoints

    def _test_endpoint(self, endpoint: dict[str, Any], base_url: str) -> dict[str, Any]:
        """Test a single endpoint. Returns {"success": bool, "error": str?}."""
        # TODO: Implement actual HTTP testing with requests
        # For now, return placeholder
        return {
            "success": True,
            "error": None,
        }

    def _create_incident(self, component: str, env: str, failures: list[dict[str, Any]]) -> None:
        """Create an incident ticket for validation failures."""
        self.stdout.write("")
        self.stdout.write(self.style.WARNING("Creating incident..."))
        self.stdout.write(f"  Component: {component}")
        self.stdout.write(f"  Environment: {env}")
        self.stdout.write(f"  Failures: {len(failures)}")
        # TODO: Implement incident creation via createOS or external system
        self.stdout.write(self.style.WARNING("  TODO: Implement incident creation"))
