"""Configuration for the EPUB search app."""

from __future__ import annotations

from dataclasses import dataclass
from os import getenv


def getenv_bool(name: str, *, default: bool) -> bool:
    """Read a boolean environment variable with a default fallback."""
    value = getenv(name)
    if value is None:
        return default
    return value.strip().lower() in {"1", "true", "yes", "on"}


def getenv_int(name: str, *, default: int) -> int:
    """Read an integer environment variable with a default fallback."""
    value = getenv(name)
    if value is None or not value.strip():
        return default
    return int(value)


@dataclass(frozen=True)
class RerankConfig:
    """vLLM reranker settings."""

    enabled: bool = False
    base_url: str = "http://192.168.90.25:8001"
    model: str = "qwen3-reranker-06b"
    candidates: int = 24
    timeout_seconds: float = 30.0


@dataclass(frozen=True)
class EbookSearchConfig:
    """Runtime settings for EPUB search."""

    rerank: RerankConfig
    top_k: int = 12
    library_paths: tuple[str, ...] = ()
    vllm_base_url: str = "https://ollama.com/v1"
    vllm_api_key: str = "not-needed"
    chat_model: str = "deepseek-v4-flash"
    answer_enabled: bool = True
    embedding_base_url: str = "http://192.168.90.25:8000/v1"
    embedding_api_key: str = "not-needed"
    embedding_model: str = "qwen3-embedding-0.6b"
    embedding_batch_size: int = 32
    bm25_index_dir: str = ".ebook_search_bm25"
    bm25_refresh_delay_seconds: int = 60


def load_rerank_config() -> RerankConfig:
    """Load reranker config from environment variables."""
    return RerankConfig(
        enabled=getenv_bool("EBOOK_SEARCH_RERANK_ENABLED", default=False),
        base_url=getenv("EBOOK_SEARCH_RERANK_BASE_URL", "http://192.168.90.25:8001"),
        model=getenv("EBOOK_SEARCH_RERANK_MODEL", "qwen3-reranker-06b"),
        candidates=getenv_int("EBOOK_SEARCH_RERANK_CANDIDATES", default=24),
        timeout_seconds=float(getenv_int("EBOOK_SEARCH_RERANK_TIMEOUT_SECONDS", default=30)),
    )


def load_config() -> EbookSearchConfig:
    """Load EPUB search config from environment variables."""
    return EbookSearchConfig(
        rerank=load_rerank_config(),
        top_k=getenv_int("EBOOK_SEARCH_TOP_K", default=12),
        library_paths=library_paths_from_env(),
        vllm_base_url=getenv("EBOOK_SEARCH_VLLM_BASE_URL", "https://ollama.com/v1"),
        vllm_api_key=getenv("EBOOK_SEARCH_VLLM_API_KEY") or getenv("OLLAMA_API_KEY") or "not-needed",
        chat_model=getenv("EBOOK_SEARCH_CHAT_MODEL", "deepseek-v4-flash"),
        answer_enabled=getenv_bool("EBOOK_SEARCH_ANSWER_ENABLED", default=True),
        embedding_base_url=getenv("EBOOK_SEARCH_EMBEDDING_BASE_URL", "http://192.168.90.25:8000/v1"),
        embedding_api_key=getenv("EBOOK_SEARCH_EMBEDDING_API_KEY", "not-needed"),
        embedding_model=normalize_embedding_model(),
        embedding_batch_size=getenv_int("EBOOK_SEARCH_EMBEDDING_BATCH_SIZE", default=32),
        bm25_index_dir=getenv("EBOOK_SEARCH_BM25_INDEX_DIR", ".ebook_search_bm25"),
        bm25_refresh_delay_seconds=getenv_int("EBOOK_SEARCH_BM25_REFRESH_DELAY_SECONDS", default=60),
    )


def normalize_embedding_model(default: str = "qwen3-embedding-0.6b") -> str:
    """Normalize supported embedding aliases to provider model names."""
    aliases = {
        "Qwen3-Embedding-0.6B": "qwen3-embedding-0.6b",
        "Qwen3-Embedding-4B": "qwen3-embedding-4b",
        "Qwen3-Embedding-8B": "qwen3-embedding-8b",
        "Qwen/Qwen3-Embedding-0.6B": "qwen3-embedding-0.6b",
        "Qwen/Qwen3-Embedding-4B": "qwen3-embedding-4b",
        "Qwen/Qwen3-Embedding-8B": "qwen3-embedding-8b",
        "qwen3-embedding:0.6b": "qwen3-embedding-0.6b",
        "qwen3-embedding:4b": "qwen3-embedding-4b",
        "qwen3-embedding:8b": "qwen3-embedding-8b",
        "qwen3-embedding-0.6b": "qwen3-embedding-0.6b",
        "qwen3-embedding-4b": "qwen3-embedding-4b",
        "qwen3-embedding-8b": "qwen3-embedding-8b",
    }

    model = getenv("EBOOK_SEARCH_EMBEDDING_MODEL", default)
    standard_model = aliases.get(model)

    if standard_model is None:
        error = f"Embedding model {model} is not supported. Supported models are {aliases.keys()}"
        raise ValueError(error)

    return standard_model


def library_paths_from_env() -> tuple[str, ...]:
    """Read configured EPUB library paths from the environment."""
    value = getenv("EBOOK_SEARCH_LIBRARY_PATHS")
    if value is None:
        return ()
    return tuple(path for path in value.split(":") if path)
