from __future__ import annotations

import os
from dataclasses import dataclass
from pathlib import Path

DEFAULT_MAX_BYTES = 1_000_000
DEFAULT_CHUNK_LINES = 120
DEFAULT_CHUNK_OVERLAP = 20
DEFAULT_EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
DEFAULT_OPENAI_EMBED_MODEL = "text-embedding-3-small"


@dataclass(frozen=True)
class EmbeddingConfig:
    provider: str
    model: str
    openai_api_key: str | None
    openai_base_url: str | None


@dataclass(frozen=True)
class Config:
    max_bytes: int
    chunk_lines: int
    chunk_overlap: int
    embeddings: EmbeddingConfig
    index_root: Path
    quiet_external_libs: bool


class ConfigError(RuntimeError):
    pass


def _env_bool(name: str, default: bool) -> bool:
    raw = os.getenv(name)
    if raw is None:
        return default
    value = raw.strip().lower()
    if value in {"1", "true", "yes", "on"}:
        return True
    if value in {"0", "false", "no", "off"}:
        return False
    return default


_EXTERNAL_LIBS_CONFIGURED = False


def configure_external_libs(quiet: bool) -> None:
    global _EXTERNAL_LIBS_CONFIGURED
    if not quiet or _EXTERNAL_LIBS_CONFIGURED:
        return

    os.environ["HF_HUB_DISABLE_PROGRESS_BARS"] = "1"
    os.environ["TRANSFORMERS_VERBOSITY"] = "error"
    os.environ["TOKENIZERS_PARALLELISM"] = "false"
    os.environ["PYTHONWARNINGS"] = "ignore"
    os.environ.setdefault("HF_HUB_DISABLE_TELEMETRY", "1")
    os.environ.setdefault("OMP_NUM_THREADS", "1")
    os.environ.setdefault("MKL_NUM_THREADS", "1")
    os.environ.setdefault("VECLIB_MAXIMUM_THREADS", "1")
    os.environ.setdefault("NUMEXPR_NUM_THREADS", "1")

    import logging

    logging.getLogger("transformers").setLevel(logging.ERROR)
    logging.getLogger("sentence_transformers").setLevel(logging.ERROR)
    logging.getLogger("huggingface_hub").setLevel(logging.ERROR)

    try:
        from transformers.utils import logging as transformers_logging

        transformers_logging.set_verbosity_error()
        if hasattr(transformers_logging, "disable_progress_bar"):
            transformers_logging.disable_progress_bar()
    except Exception:
        pass

    _EXTERNAL_LIBS_CONFIGURED = True


def load_config() -> Config:
    provider = os.getenv("MIKOSHI_EMBEDDINGS_PROVIDER", "local").strip().lower()
    if provider not in {"local", "openai"}:
        raise ConfigError(
            "MIKOSHI_EMBEDDINGS_PROVIDER must be 'local' or 'openai'."
        )

    model = os.getenv("MIKOSHI_EMBEDDINGS_MODEL", DEFAULT_EMBEDDING_MODEL)
    openai_model = os.getenv("MIKOSHI_OPENAI_EMBED_MODEL", DEFAULT_OPENAI_EMBED_MODEL)

    openai_api_key = os.getenv("MIKOSHI_OPENAI_API_KEY") or os.getenv("OPENAI_API_KEY")
    openai_base_url = os.getenv("MIKOSHI_OPENAI_BASE_URL") or os.getenv("OPENAI_BASE_URL")

    if provider == "openai":
        if not openai_api_key:
            raise ConfigError(
                "OpenAI embeddings selected but no API key found. "
                "Set MIKOSHI_OPENAI_API_KEY or OPENAI_API_KEY."
            )
        model = openai_model

    index_root = Path(os.getenv("MIKOSHI_INDEX_ROOT", "~/.mikoshi")).expanduser()
    max_bytes = int(os.getenv("MIKOSHI_MAX_BYTES", str(DEFAULT_MAX_BYTES)))
    chunk_lines = int(os.getenv("MIKOSHI_CHUNK_LINES", str(DEFAULT_CHUNK_LINES)))
    chunk_overlap = int(os.getenv("MIKOSHI_CHUNK_OVERLAP", str(DEFAULT_CHUNK_OVERLAP)))
    quiet_external_libs = _env_bool("MIKOSHI_QUIET_EXTERNAL_LIBS", True)

    embeddings = EmbeddingConfig(
        provider=provider,
        model=model,
        openai_api_key=openai_api_key,
        openai_base_url=openai_base_url,
    )

    return Config(
        max_bytes=max_bytes,
        chunk_lines=chunk_lines,
        chunk_overlap=chunk_overlap,
        embeddings=embeddings,
        index_root=index_root,
        quiet_external_libs=quiet_external_libs,
    )
