"""Registry for tracking review status of modules."""

from __future__ import annotations

import json
from dataclasses import asdict, dataclass, field
from datetime import datetime, timezone
from pathlib import Path
from typing import Iterator

SCHEMA_VERSION = "1"


@dataclass
class ModuleStatus:
    """Review status for a single module."""

    path: str
    status: str = "needs_review"  # needs_review, in_progress, reviewed, needs_update
    priority: str = "medium"
    lines: int = 0
    reviewers_required: int = 1
    last_reviewed_commit: str | None = None
    last_reviewed_date: str | None = None
    reviewers: list[str] = field(default_factory=list)
    review_issue: str | None = None
    assigned_reviewer: str | None = None
    review_started_commit: str | None = None  # Commit when review was started
    notes: str = ""

    def to_dict(self) -> dict:
        """Convert to dictionary for JSON serialization."""
        return {k: v for k, v in asdict(self).items() if k != "path"}

    @classmethod
    def from_dict(cls, path: str, data: dict) -> "ModuleStatus":
        """Create from dictionary."""
        return cls(
            path=path,
            status=data.get("status", "needs_review"),
            priority=data.get("priority", "medium"),
            lines=data.get("lines", 0),
            reviewers_required=data.get("reviewers_required", 1),
            last_reviewed_commit=data.get("last_reviewed_commit"),
            last_reviewed_date=data.get("last_reviewed_date"),
            reviewers=data.get("reviewers", []),
            review_issue=data.get("review_issue"),
            assigned_reviewer=data.get("assigned_reviewer"),
            review_started_commit=data.get("review_started_commit"),
            notes=data.get("notes", ""),
        )


@dataclass
class Registry:
    """Registry of module review statuses."""

    modules: dict[str, ModuleStatus] = field(default_factory=dict)
    last_updated: str | None = None
    current_commit: str | None = None

    def get(self, path: str) -> ModuleStatus | None:
        """Get the status for a module."""
        return self.modules.get(path)

    def set(self, status: ModuleStatus) -> None:
        """Set the status for a module."""
        self.modules[status.path] = status

    def remove(self, path: str) -> bool:
        """Remove a module from the registry. Returns True if it existed."""
        if path in self.modules:
            del self.modules[path]
            return True
        return False

    def __iter__(self) -> Iterator[ModuleStatus]:
        """Iterate over all module statuses."""
        return iter(self.modules.values())

    def __len__(self) -> int:
        """Return the number of modules in the registry."""
        return len(self.modules)

    def filter(
        self,
        status: str | None = None,
        priority: str | None = None,
    ) -> Iterator[ModuleStatus]:
        """Filter modules by status and/or priority."""
        for module in self:
            if status and module.status != status:
                continue
            if priority and module.priority != priority:
                continue
            yield module

    @property
    def summary(self) -> dict[str, int]:
        """Get a summary of review statuses."""
        counts = {
            "total": 0,
            "reviewed": 0,
            "needs_review": 0,
            "in_progress": 0,
            "needs_update": 0,
            "total_lines": 0,
            "reviewed_lines": 0,
        }
        for module in self:
            counts["total"] += 1
            counts["total_lines"] += module.lines

            if module.status == "reviewed":
                counts["reviewed"] += 1
                counts["reviewed_lines"] += module.lines
            elif module.status == "in_progress":
                counts["in_progress"] += 1
            elif module.status in ("needs_review", "needs_update"):
                counts[module.status] += 1

        return counts

    def to_dict(self) -> dict:
        """Convert to dictionary for JSON serialization."""
        return {
            "version": SCHEMA_VERSION,
            "last_updated": self.last_updated,
            "current_commit": self.current_commit,
            "modules": {path: mod.to_dict() for path, mod in self.modules.items()},
        }

    @classmethod
    def from_dict(cls, data: dict) -> "Registry":
        """Create from dictionary."""
        modules = {}
        for path, mod_data in data.get("modules", {}).items():
            modules[path] = ModuleStatus.from_dict(path, mod_data)

        return cls(
            modules=modules,
            last_updated=data.get("last_updated"),
            current_commit=data.get("current_commit"),
        )


def load_registry(path: Path) -> Registry:
    """Load registry from a JSON file.

    Args:
        path: Path to the registry file.

    Returns:
        Registry object. Returns empty registry if file doesn't exist.
    """
    if not path.exists():
        return Registry()

    with open(path) as f:
        data = json.load(f)

    return Registry.from_dict(data)


def save_registry(registry: Registry, path: Path, commit: str | None = None) -> None:
    """Save registry to a JSON file.

    Args:
        registry: Registry to save.
        path: Path to write to.
        commit: Current git commit SHA to record.
    """
    registry.last_updated = datetime.now(timezone.utc).isoformat()
    if commit:
        registry.current_commit = commit

    with open(path, "w") as f:
        json.dump(registry.to_dict(), f, indent=2)
        f.write("\n")
