"""
Registry — a shared folder-based store for team prompts.
Push prompts in. Pull them out anywhere.
"""

import json
from pathlib import Path
from typing import List, Optional

import yaml

from .prompt import Prompt


class Registry:
    """
    A folder-based prompt registry for sharing prompts across a team.

    The registry is just a directory. Each prompt gets a subfolder.
    Each version is a YAML file. An index.json tracks everything.

    Example:
        >>> reg = Registry("./shared_prompts")
        >>> reg.push(my_prompt)
        >>> p = reg.pull("summarize")           # latest
        >>> p = reg.pull("summarize", "v1")     # specific version
        >>> print(reg.list())
    """

    def __init__(self, path: str):
        self.path = Path(path)
        self.path.mkdir(parents=True, exist_ok=True)
        self._index_path = self.path / "index.json"
        self._ensure_index()

    def _ensure_index(self):
        if not self._index_path.exists():
            self._index_path.write_text(json.dumps({}))

    def _load_index(self) -> dict:
        try:
            return json.loads(self._index_path.read_text())
        except (json.JSONDecodeError, FileNotFoundError):
            return {}

    def _save_index(self, data: dict):
        self._index_path.write_text(json.dumps(data, indent=2))

    def push(self, prompt: Prompt) -> str:
        """
        Push a prompt to the registry.

        Returns:
            Path to the saved file.
        """
        prompt_dir = self.path / prompt.name
        prompt_dir.mkdir(exist_ok=True)

        filepath = prompt_dir / f"{prompt.version}.yaml"
        with open(filepath, "w") as f:
            yaml.dump(
                {
                    "name":        prompt.name,
                    "version":     prompt.version,
                    "description": prompt.description,
                    "template":    prompt.template,
                    "tags":        prompt.tags,
                    "metadata":    prompt.metadata,
                    "created_at":  prompt.created_at,
                },
                f,
                default_flow_style=False,
                allow_unicode=True,
            )

        # Update index
        index = self._load_index()
        if prompt.name not in index:
            index[prompt.name] = {"versions": [], "latest": None}
        if prompt.version not in index[prompt.name]["versions"]:
            index[prompt.name]["versions"].append(prompt.version)
        index[prompt.name]["latest"] = prompt.version
        self._save_index(index)

        return str(filepath)

    def pull(self, name: str, version: str = "latest") -> Prompt:
        """
        Pull a prompt from the registry.

        Args:
            name:    Prompt name.
            version: 'latest' or a specific version like 'v2'.

        Returns:
            A Prompt instance.
        """
        index = self._load_index()
        if name not in index:
            available = list(index.keys())
            raise KeyError(
                f"Prompt '{name}' not found in registry. "
                f"Available: {available}"
            )

        resolved = index[name]["latest"] if version == "latest" else version

        if resolved not in index[name]["versions"]:
            raise KeyError(
                f"Version '{version}' not found for '{name}'. "
                f"Available: {index[name]['versions']}"
            )

        filepath = self.path / name / f"{resolved}.yaml"
        return Prompt.load(str(filepath))

    def list(self) -> List[str]:
        """Return all prompt names in the registry."""
        return list(self._load_index().keys())

    def versions(self, name: str) -> List[str]:
        """Return all versions for a given prompt."""
        index = self._load_index()
        if name not in index:
            raise KeyError(f"Prompt '{name}' not found in registry.")
        return index[name]["versions"]

    def delete(self, name: str, version: Optional[str] = None) -> bool:
        """
        Delete a prompt or a specific version from the registry.

        If version is None, deletes all versions.
        """
        index = self._load_index()
        if name not in index:
            return False

        if version is None:
            import shutil
            shutil.rmtree(self.path / name, ignore_errors=True)
            del index[name]
        else:
            filepath = self.path / name / f"{version}.yaml"
            if filepath.exists():
                filepath.unlink()
            index[name]["versions"] = [
                v for v in index[name]["versions"] if v != version
            ]
            if not index[name]["versions"]:
                del index[name]
            elif index[name]["latest"] == version:
                index[name]["latest"] = index[name]["versions"][-1]

        self._save_index(index)
        return True

    def __repr__(self) -> str:
        return f"Registry(path='{self.path}', prompts={self.list()})"
