"""YAML config support for the llmindex CLI.

The default config file generated by `llmindex init` is `llmindex.yaml`.
"""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Any

import yaml


class ConfigError(RuntimeError):
    """Raised when a YAML config cannot be read or validated."""


@dataclass(frozen=True)
class LLMIndexYamlConfig:
    site_name: str | None = None
    base_url: str | None = None
    language: str | None = None
    topics: list[str] | None = None


def _parse_topics(value: Any) -> list[str] | None:
    if value is None:
        return None
    if isinstance(value, list):
        topics = [str(item).strip() for item in value if str(item).strip()]
        return topics or None
    if isinstance(value, str):
        topics = [part.strip() for part in value.split(",") if part.strip()]
        return topics or None
    raise ConfigError("topics must be a list of strings or a comma-separated string")


def load_yaml_config(path: Path) -> LLMIndexYamlConfig:
    """Load `llmindex.yaml`-style config from disk.

    Expected keys:
      - site_name: str
      - base_url: str
      - language: str
      - topics: list[str] | "a,b,c"
    """
    if not path.exists():
        raise ConfigError(f"Config file not found: {path}")

    try:
        raw = yaml.safe_load(path.read_text(encoding="utf-8"))
    except (OSError, UnicodeDecodeError) as e:
        raise ConfigError(f"Failed to read config: {e}") from e
    except yaml.YAMLError as e:
        raise ConfigError(f"Invalid YAML: {e}") from e

    if raw is None:
        return LLMIndexYamlConfig()
    if not isinstance(raw, dict):
        raise ConfigError("Config must be a YAML mapping (key/value object)")

    site_name = raw.get("site_name")
    base_url = raw.get("base_url")
    language = raw.get("language")
    topics = _parse_topics(raw.get("topics"))

    if site_name is not None and not isinstance(site_name, str):
        raise ConfigError("site_name must be a string")
    if base_url is not None and not isinstance(base_url, str):
        raise ConfigError("base_url must be a string")
    if language is not None and not isinstance(language, str):
        raise ConfigError("language must be a string")

    return LLMIndexYamlConfig(
        site_name=site_name.strip() if isinstance(site_name, str) else None,
        base_url=base_url.strip() if isinstance(base_url, str) else None,
        language=language.strip() if isinstance(language, str) else None,
        topics=topics,
    )
