"""Configuration management for Meeting Helper."""

from __future__ import annotations

import functools
import json
import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any

HOME = Path.home()
DEFAULT_CONFIG_DIR = HOME / ".config" / "meeting-helper"
CONFIG_FILE = DEFAULT_CONFIG_DIR / "config.json"
PID_FILE = HOME / ".meeting-helper.pid"
META_FILE = HOME / ".meeting-helper.meta.json"
LOG_FILE = HOME / ".meeting-helper.log"

CLAUDE_MODELS = {
    "sonnet": "claude-sonnet-4-6",
    "opus": "claude-opus-4-6",
    "haiku": "claude-haiku-4-5-20251001",
}

DEFAULT_CONFIG: dict[str, Any] = {
    "anthropic_api_key": "",
    "deepgram_api_key": "",
    "port": 7891,
    "recordings_dir": str(HOME / "meetings"),
    "repos": [],
    "knowledge_path": "",
    "sentence_window": 5,
    "max_history_turns": 5,
    "claude_model": "sonnet",
    "max_tokens": 2048,
    "transcription_language": "en",
    "silence_timeout": 30,
    "setup_complete": False,
}


class Config:
    """JSON-backed configuration manager."""

    def __init__(self, config_path: Path = CONFIG_FILE):
        self.config_path = config_path
        self._data: dict[str, Any] = {}
        self.load()

    def load(self) -> None:
        if self.config_path.exists():
            try:
                with open(self.config_path) as f:
                    self._data = json.load(f)
            except (json.JSONDecodeError, IOError):
                self._data = {}
        else:
            self._data = {}
        for key, value in DEFAULT_CONFIG.items():
            if key not in self._data:
                self._data[key] = value

    def save(self) -> None:
        self.config_path.parent.mkdir(parents=True, exist_ok=True)
        with open(self.config_path, "w") as f:
            json.dump(self._data, f, indent=2)

    @property
    def anthropic_api_key(self) -> str:
        return (self._data.get("anthropic_api_key") or os.environ.get("ANTHROPIC_API_KEY", "")).strip()

    @anthropic_api_key.setter
    def anthropic_api_key(self, value: str) -> None:
        self._data["anthropic_api_key"] = value

    @property
    def deepgram_api_key(self) -> str:
        return self._data.get("deepgram_api_key", "").strip()

    @deepgram_api_key.setter
    def deepgram_api_key(self, value: str) -> None:
        self._data["deepgram_api_key"] = value

    @property
    def port(self) -> int:
        return int(self._data.get("port", 7891))

    @port.setter
    def port(self, value: int) -> None:
        self._data["port"] = value

    @property
    def recordings_dir(self) -> Path:
        return Path(self._data["recordings_dir"]).expanduser()

    @recordings_dir.setter
    def recordings_dir(self, value: Path | str) -> None:
        self._data["recordings_dir"] = str(value)

    @property
    def repos(self) -> list[str]:
        return self._data.get("repos", [])

    @repos.setter
    def repos(self, value: list[str]) -> None:
        self._data["repos"] = value

    @property
    def knowledge_path(self) -> str:
        return self._data.get("knowledge_path", "")

    @knowledge_path.setter
    def knowledge_path(self, value: str) -> None:
        self._data["knowledge_path"] = value

    @property
    def sentence_window(self) -> int:
        return int(self._data.get("sentence_window", 5))

    @sentence_window.setter
    def sentence_window(self, value: int) -> None:
        self._data["sentence_window"] = value

    @property
    def max_history_turns(self) -> int:
        return int(self._data.get("max_history_turns", 5))

    @max_history_turns.setter
    def max_history_turns(self, value: int) -> None:
        self._data["max_history_turns"] = value

    @property
    def claude_model(self) -> str:
        alias = self._data.get("claude_model", "sonnet")
        return CLAUDE_MODELS.get(alias, alias)

    @claude_model.setter
    def claude_model(self, value: str) -> None:
        self._data["claude_model"] = value

    @property
    def max_tokens(self) -> int:
        return int(self._data.get("max_tokens", 2048))

    @max_tokens.setter
    def max_tokens(self, value: int) -> None:
        self._data["max_tokens"] = value

    @property
    def transcription_language(self) -> str:
        return self._data.get("transcription_language", "en")

    @transcription_language.setter
    def transcription_language(self, value: str) -> None:
        self._data["transcription_language"] = value

    @property
    def silence_timeout(self) -> int:
        return int(self._data.get("silence_timeout", 30))

    @silence_timeout.setter
    def silence_timeout(self, value: int) -> None:
        self._data["silence_timeout"] = value

    @property
    def setup_complete(self) -> bool:
        return self._data.get("setup_complete", False)

    @setup_complete.setter
    def setup_complete(self, value: bool) -> None:
        self._data["setup_complete"] = value

    def to_app_config(self) -> AppConfig:
        """Build runtime AppConfig — starts with NO workspace context.

        User selectively loads repos/knowledge via the Dashboard context
        selector during a meeting.
        """
        from meeting_helper.ai.prompts import build_system_prompt

        system_prompt = build_system_prompt("")

        return AppConfig(
            anthropic_api_key=self.anthropic_api_key,
            deepgram_api_key=self.deepgram_api_key,
            port=self.port,
            recordings_dir=self.recordings_dir,
            repos=list(self.repos),
            knowledge_path=self.knowledge_path,
            sentence_window=self.sentence_window,
            max_history_turns=self.max_history_turns,
            claude_model=self.claude_model,
            max_tokens=self.max_tokens,
            transcription_language=self.transcription_language,
            silence_timeout=self.silence_timeout,
            system_prompt=system_prompt,
        )

    def __getitem__(self, key: str) -> Any:
        return self._data.get(key, DEFAULT_CONFIG.get(key))

    def __setitem__(self, key: str, value: Any) -> None:
        self._data[key] = value


@dataclass
class AppConfig:
    """Immutable runtime config used by the daemon."""

    anthropic_api_key: str = ""
    deepgram_api_key: str = ""
    port: int = 7891
    recordings_dir: Path = field(default_factory=lambda: Path.home() / "meetings")
    repos: list[str] = field(default_factory=list)
    knowledge_path: str = ""
    sentence_window: int = 5
    max_history_turns: int = 5
    claude_model: str = "claude-sonnet-4-6"
    max_tokens: int = 2048
    transcription_language: str = "en"
    silence_timeout: int = 30
    system_prompt: str = ""


# Global config instance (lazy loaded)
_config: Config | None = None


def get_config(reload: bool = False) -> Config:
    """Get the global config instance."""
    global _config
    if _config is None:
        _config = Config()
    elif reload:
        _config.load()
    return _config


def require_setup(f):
    """Decorator: ensures config directories exist."""
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        config = get_config()
        config.recordings_dir.mkdir(parents=True, exist_ok=True)
        return f(*args, **kwargs)
    return wrapper
