"""Project metadata management for Spec Kitty upgrade system."""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime
from pathlib import Path
from typing import List, Optional

import yaml


@dataclass
class MigrationRecord:
    """Record of a single migration application."""

    id: str
    applied_at: datetime
    result: str  # "success", "skipped", "failed"
    notes: Optional[str] = None


@dataclass
class ProjectMetadata:
    """Metadata for a Spec Kitty project stored in .kittify/metadata.yaml."""

    version: str
    initialized_at: datetime
    last_upgraded_at: Optional[datetime] = None
    python_version: str = ""
    platform: str = ""
    platform_version: str = ""
    applied_migrations: List[MigrationRecord] = field(default_factory=list)

    @classmethod
    def load(cls, kittify_dir: Path) -> Optional["ProjectMetadata"]:
        """Load metadata from .kittify/metadata.yaml.

        Args:
            kittify_dir: Path to the .kittify directory

        Returns:
            ProjectMetadata if file exists, None otherwise
        """
        metadata_path = kittify_dir / "metadata.yaml"
        if not metadata_path.exists():
            return None

        try:
            with open(metadata_path, "r", encoding="utf-8-sig") as f:
                data = yaml.safe_load(f)
        except (OSError, yaml.YAMLError):
            return None

        if not data:
            return None

        spec_kitty = data.get("spec_kitty", {})
        env = data.get("environment", {})
        migrations_data = data.get("migrations", {}).get("applied", [])

        applied = []
        for m in migrations_data:
            try:
                applied.append(
                    MigrationRecord(
                        id=m["id"],
                        applied_at=datetime.fromisoformat(m["applied_at"]),
                        result=m["result"],
                        notes=m.get("notes"),
                    )
                )
            except (KeyError, ValueError):
                # Skip malformed migration records
                continue

        initialized_at_str = spec_kitty.get("initialized_at")
        try:
            initialized_at = (
                datetime.fromisoformat(initialized_at_str)
                if initialized_at_str
                else datetime.now()
            )
        except ValueError:
            initialized_at = datetime.now()

        last_upgraded_str = spec_kitty.get("last_upgraded_at")
        try:
            last_upgraded_at = (
                datetime.fromisoformat(last_upgraded_str) if last_upgraded_str else None
            )
        except ValueError:
            last_upgraded_at = None

        return cls(
            version=spec_kitty.get("version", "unknown"),
            initialized_at=initialized_at,
            last_upgraded_at=last_upgraded_at,
            python_version=env.get("python_version", ""),
            platform=env.get("platform", ""),
            platform_version=env.get("platform_version", ""),
            applied_migrations=applied,
        )

    def save(self, kittify_dir: Path) -> None:
        """Save metadata to .kittify/metadata.yaml.

        Args:
            kittify_dir: Path to the .kittify directory
        """
        metadata_path = kittify_dir / "metadata.yaml"
        kittify_dir.mkdir(parents=True, exist_ok=True)

        data = {
            "spec_kitty": {
                "version": self.version,
                "initialized_at": self.initialized_at.isoformat(),
                "last_upgraded_at": (
                    self.last_upgraded_at.isoformat() if self.last_upgraded_at else None
                ),
            },
            "environment": {
                "python_version": self.python_version,
                "platform": self.platform,
                "platform_version": self.platform_version,
            },
            "migrations": {
                "applied": [
                    {
                        "id": m.id,
                        "applied_at": m.applied_at.isoformat(),
                        "result": m.result,
                        "notes": m.notes,
                    }
                    for m in self.applied_migrations
                ]
            },
        }

        # Add header comment
        header = (
            "# Spec Kitty Project Metadata\n"
            "# Auto-generated by spec-kitty init/upgrade\n"
            "# DO NOT EDIT MANUALLY\n\n"
        )

        with open(metadata_path, "w", encoding="utf-8") as f:
            f.write(header)
            yaml.dump(data, f, default_flow_style=False, sort_keys=False)

    def has_migration(self, migration_id: str) -> bool:
        """Check if a migration has been successfully applied.

        Args:
            migration_id: The ID of the migration to check

        Returns:
            True if migration was applied successfully
        """
        return any(
            m.id == migration_id and m.result == "success"
            for m in self.applied_migrations
        )

    def record_migration(
        self, migration_id: str, result: str, notes: Optional[str] = None
    ) -> None:
        """Record a migration application.

        Args:
            migration_id: The ID of the migration
            result: The result ("success", "skipped", "failed")
            notes: Optional notes about the migration
        """
        self.applied_migrations.append(
            MigrationRecord(
                id=migration_id,
                applied_at=datetime.now(),
                result=result,
                notes=notes,
            )
        )
