from __future__ import annotations

from pathlib import Path
from typing import Any

from common import ROOT, read_yaml_mapping


DEFAULT_PROFILES = ROOT / "plugins" / "1c" / "rag" / "profiles.yaml"
DEFAULT_PROFILE = "auto"

PROFILE_KEYWORDS = {
    "metadata": [
        "метадан",
        "реквизит",
        "табличн",
        "справочник",
        "документ",
        "регистр",
        "форма",
        "объект",
        "конфигурац",
    ],
    "bsl": [
        "bsl",
        "бсл",
        "код",
        "процедур",
        "функц",
        "модул",
        "ошибк",
        "переменн",
        "конецесли",
        "передзаписью",
    ],
    "query": [
        "запрос",
        "выбрать",
        "срез",
        "остатк",
        "read-only",
        "readonly",
        "sql",
    ],
    "safe-change": [
        "измен",
        "переимен",
        "production",
        "прод",
        "резерв",
        "backup",
        "соглас",
        "безопас",
        "удалить",
    ],
}


def load_rag_profiles(path: Path = DEFAULT_PROFILES) -> dict[str, dict[str, Any]]:
    data = read_yaml_mapping(path)
    profiles = data.get("profiles")
    if not isinstance(profiles, dict):
        raise ValueError(f"{path} must contain a profiles mapping")
    return {str(name): dict(value or {}) for name, value in profiles.items()}


def get_rag_profile(name: str | None, path: Path = DEFAULT_PROFILES) -> dict[str, Any]:
    profiles = load_rag_profiles(path)
    profile_name = name or DEFAULT_PROFILE
    if profile_name not in profiles:
        available = ", ".join(sorted(profiles))
        raise ValueError(f"Unknown RAG profile `{profile_name}`. Available: {available}")
    profile = profiles[profile_name]
    profile["id"] = profile_name
    profile.setdefault("source_types", [])
    profile.setdefault("limit", 4)
    profile.setdefault("candidate_limit", 40)
    profile.setdefault("min_score", 0.0)
    profile.setdefault("max_context_chars", 12000)
    profile.setdefault("dedupe_by_document", False)
    return profile


def detect_rag_profile(question: str) -> str:
    text = question.lower().replace("ё", "е")
    scores = {
        profile: sum(1 for keyword in keywords if keyword in text)
        for profile, keywords in PROFILE_KEYWORDS.items()
    }
    best_profile, best_score = max(scores.items(), key=lambda item: item[1])
    return best_profile if best_score > 0 else "general"


def resolve_rag_profile(name: str | None, question: str, path: Path = DEFAULT_PROFILES) -> dict[str, Any]:
    profile_name = name or DEFAULT_PROFILE
    if profile_name == "auto":
        profile_name = detect_rag_profile(question)
    return get_rag_profile(profile_name, path)


def list_rag_profiles(path: Path = DEFAULT_PROFILES) -> list[dict[str, Any]]:
    return [get_rag_profile(name, path) for name in sorted(load_rag_profiles(path))]
