"""
ShelfAI configuration loader and validator.

Handles loading shelf.config.yaml and providing typed access to settings.
"""

from dataclasses import dataclass, field
from pathlib import Path

import yaml


@dataclass
class SessionConfig:
    """Settings for the session management agent."""

    provider: str = "anthropic"
    model: str = "claude-sonnet-4-20250514"
    api_key_env: str = "ANTHROPIC_API_KEY"

    # What to extract
    extract_user_preferences: bool = True
    extract_agent_lessons: bool = True
    extract_task_patterns: bool = True
    extract_knowledge_corrections: bool = True
    extract_new_context: bool = True
    extract_abstract_updates: bool = True

    # Safety
    auto_apply_corrections: bool = False
    require_high_confidence: bool = False

    # Memory limits
    max_entries_per_file: int = 100
    dedup_strategy: str = "llm"
    conflict_resolution: str = "flag"
    new_context_mode: str = "stage"  # stage|apply
    new_context_stage_dir: str = "generated/review/new_context"
    new_context_allowed_categories: list[str] = field(default_factory=lambda: ["memory"])


@dataclass
class IndexConfig:
    """Settings for the index."""

    max_abstract_length: int = 300
    auto_rebuild: bool = True
    abstract_min_length: int = 24
    abstract_max_length: int = 300


@dataclass
class ShelfConfig:
    """
    Top-level ShelfAI configuration.

    Loaded from shelf.config.yaml in the shelf root directory.
    """

    version: str = "1.0"
    project_name: str = ""
    project_description: str = ""
    categories: list = field(default_factory=lambda: ["skills", "knowledge", "memory", "resources"])
    session: SessionConfig = field(default_factory=SessionConfig)
    index: IndexConfig = field(default_factory=IndexConfig)

    @classmethod
    def load(cls, path: Path) -> "ShelfConfig":
        """
        Load configuration from a YAML file.

        Args:
            path: Path to shelf.config.yaml

        Returns:
            Populated ShelfConfig instance

        Raises:
            FileNotFoundError: If the config file doesn't exist
            yaml.YAMLError: If the YAML is malformed
        """
        if not path.exists():
            raise FileNotFoundError(f"Config file not found: {path}")

        with open(path, "r") as f:
            raw = yaml.safe_load(f) or {}

        config = cls()
        config.version = raw.get("version", "1.0")

        # Project settings
        project = raw.get("project", {})
        config.project_name = project.get("name", "")
        config.project_description = project.get("description", "")

        # Categories
        config.categories = raw.get("categories", config.categories)

        # Session settings
        session_raw = raw.get("session", {})
        config.session = SessionConfig(
            provider=session_raw.get("provider", "anthropic"),
            model=session_raw.get("model", "claude-sonnet-4-20250514"),
            api_key_env=session_raw.get("api_key_env", "ANTHROPIC_API_KEY"),
            extract_user_preferences=session_raw.get("extract", {}).get(
                "user_preferences", True
            ),
            extract_agent_lessons=session_raw.get("extract", {}).get("agent_lessons", True),
            extract_task_patterns=session_raw.get("extract", {}).get("task_patterns", True),
            extract_knowledge_corrections=session_raw.get("extract", {}).get(
                "knowledge_corrections", True
            ),
            extract_new_context=session_raw.get("extract", {}).get("new_context", True),
            extract_abstract_updates=session_raw.get("extract", {}).get("abstract_updates", True),
            auto_apply_corrections=session_raw.get("auto_apply_corrections", False),
            require_high_confidence=session_raw.get("require_high_confidence", False),
            max_entries_per_file=session_raw.get("memory", {}).get("max_entries_per_file", 100),
            dedup_strategy=session_raw.get("memory", {}).get("dedup_strategy", "llm"),
            conflict_resolution=session_raw.get("memory", {}).get("conflict_resolution", "flag"),
            new_context_mode=session_raw.get("new_context_mode", "stage"),
            new_context_stage_dir=session_raw.get("new_context_stage_dir", "generated/review/new_context"),
            new_context_allowed_categories=session_raw.get("new_context_allowed_categories", ["memory"]),
        )

        # Index settings
        index_raw = raw.get("index", {})
        max_len = index_raw.get("abstract_max_length", index_raw.get("max_abstract_length", 300))
        config.index = IndexConfig(
            max_abstract_length=max_len,
            auto_rebuild=index_raw.get("auto_rebuild", True),
            abstract_min_length=index_raw.get("abstract_min_length", 24),
            abstract_max_length=max_len,
        )

        return config

    @classmethod
    def default(cls) -> "ShelfConfig":
        """Return a default configuration."""
        return cls()

    def to_yaml(self) -> str:
        """Serialize the config to YAML string for writing to disk."""
        data = {
            "version": self.version,
            "project": {
                "name": self.project_name,
                "description": self.project_description,
            },
            "session": {
                "provider": self.session.provider,
                "model": self.session.model,
                "api_key_env": self.session.api_key_env,
                "extract": {
                    "user_preferences": self.session.extract_user_preferences,
                    "agent_lessons": self.session.extract_agent_lessons,
                    "task_patterns": self.session.extract_task_patterns,
                    "knowledge_corrections": self.session.extract_knowledge_corrections,
                    "new_context": self.session.extract_new_context,
                    "abstract_updates": self.session.extract_abstract_updates,
                },
                "auto_apply_corrections": self.session.auto_apply_corrections,
                "require_high_confidence": self.session.require_high_confidence,
                "memory": {
                    "max_entries_per_file": self.session.max_entries_per_file,
                    "dedup_strategy": self.session.dedup_strategy,
                    "conflict_resolution": self.session.conflict_resolution,
                },
                "new_context_mode": self.session.new_context_mode,
                "new_context_stage_dir": self.session.new_context_stage_dir,
                "new_context_allowed_categories": self.session.new_context_allowed_categories,
            },
            "index": {
                "max_abstract_length": self.index.max_abstract_length,
                "abstract_min_length": self.index.abstract_min_length,
                "abstract_max_length": self.index.abstract_max_length,
                "auto_rebuild": self.index.auto_rebuild,
            },
            "categories": self.categories,
        }
        return yaml.dump(data, default_flow_style=False, sort_keys=False)
