"""Configuration management for promptkit."""

import os
import json
from pathlib import Path
from typing import Any, Dict, Optional


DEFAULT_CONFIG = {
    "version": "1",
    "default_model": "gpt-4o",
    "default_provider": "openai",
    "prompt_format": "markdown",
    "template_engine": "jinja2",
    "diff_context_lines": 3,
    "auto_tag_latest": True,
    "providers": {
        "openai": {
            "api_base": "https://api.openai.com/v1",
            "models": ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-3.5-turbo"],
        },
        "anthropic": {
            "api_base": "https://api.anthropic.com/v1",
            "models": [
                "claude-sonnet-4-20250514",
                "claude-3-5-sonnet-20241022",
                "claude-3-haiku-20240307",
            ],
        },
        "openrouter": {
            "api_base": "https://openrouter.ai/api/v1",
            "models": [],
        },
    },
    "pricing": {
        "gpt-4o": {"input": 2.50, "output": 10.00},
        "gpt-4o-mini": {"input": 0.15, "output": 0.60},
        "gpt-4-turbo": {"input": 10.00, "output": 30.00},
        "gpt-3.5-turbo": {"input": 0.50, "output": 1.50},
        "claude-sonnet-4-20250514": {"input": 3.00, "output": 15.00},
        "claude-3-5-sonnet-20241022": {"input": 3.00, "output": 15.00},
        "claude-3-haiku-20240307": {"input": 0.25, "output": 1.25},
    },
}


class Config:
    """Manages promptkit configuration."""

    def __init__(self, project_dir: Optional[Path] = None):
        self.project_dir = project_dir or self._find_project_dir()
        self.config_dir = self.project_dir / ".promptkit" if self.project_dir else None
        self._data: Dict[str, Any] = {}
        if self.config_dir and self.config_dir.exists():
            self._load()

    @staticmethod
    def _find_project_dir() -> Optional[Path]:
        """Walk up from cwd to find .promptkit directory."""
        current = Path.cwd()
        while current != current.parent:
            if (current / ".promptkit").is_dir():
                return current
            current = current.parent
        return None

    def _load(self) -> None:
        """Load config from disk."""
        config_file = self.config_dir / "config.json"
        if config_file.exists():
            with open(config_file, "r") as f:
                self._data = json.load(f)
        else:
            self._data = dict(DEFAULT_CONFIG)

    def save(self) -> None:
        """Save config to disk."""
        if not self.config_dir:
            raise RuntimeError("No promptkit project found. Run 'promptkit init' first.")
        self.config_dir.mkdir(parents=True, exist_ok=True)
        config_file = self.config_dir / "config.json"
        with open(config_file, "w") as f:
            json.dump(self._data, f, indent=2)

    def get(self, key: str, default: Any = None) -> Any:
        """Get a config value."""
        keys = key.split(".")
        data = self._data
        for k in keys:
            if isinstance(data, dict):
                data = data.get(k)
                if data is None:
                    return default
            else:
                return default
        return data

    def set(self, key: str, value: Any) -> None:
        """Set a config value."""
        keys = key.split(".")
        data = self._data
        for k in keys[:-1]:
            if k not in data:
                data[k] = {}
            data = data[k]
        data[keys[-1]] = value

    @classmethod
    def init_project(cls, directory: Path) -> "Config":
        """Initialize a new promptkit project."""
        promptkit_dir = directory / ".promptkit"
        promptkit_dir.mkdir(parents=True, exist_ok=True)

        # Create subdirectories
        (promptkit_dir / "prompts").mkdir(exist_ok=True)
        (promptkit_dir / "tests").mkdir(exist_ok=True)
        (promptkit_dir / "cache").mkdir(exist_ok=True)

        # Create config
        config = cls(project_dir=directory)
        config._data = dict(DEFAULT_CONFIG)
        config.save()

        # Create .gitignore for cache
        gitignore = promptkit_dir / ".gitignore"
        gitignore.write_text("cache/\n*.pyc\n__pycache__/\n")

        return config

    @property
    def prompts_dir(self) -> Path:
        """Path to prompts directory."""
        if not self.config_dir:
            raise RuntimeError("No promptkit project found. Run 'promptkit init' first.")
        return self.config_dir / "prompts"

    @property
    def tests_dir(self) -> Path:
        """Path to tests directory."""
        if not self.config_dir:
            raise RuntimeError("No promptkit project found. Run 'promptkit init' first.")
        return self.config_dir / "tests"

    def get_pricing(self, model: str) -> Optional[Dict[str, float]]:
        """Get pricing for a model (per 1M tokens)."""
        pricing = self._data.get("pricing", {})
        return pricing.get(model)

    def is_initialized(self) -> bool:
        """Check if current directory is a promptkit project."""
        return self.config_dir is not None and self.config_dir.exists()
