from __future__ import annotations

import json
import os
from pathlib import Path
from typing import Any
from urllib.parse import quote_plus

from src.env_settings import load_env_candidates

ROOT = Path(__file__).resolve().parent.parent
CONFIG_PATH = ROOT / "config" / "runtime_profiles.json"
PLACEHOLDER_VALUES = {"", "change_me", "__required__", "__required_dsn__"}


def _is_placeholder(value: str) -> bool:
    return value.strip().lower() in PLACEHOLDER_VALUES


def _safe_float(value: Any, default: float) -> float:
    try:
        return float(value)
    except Exception:
        return default


def _safe_int(value: Any, default: int) -> int:
    try:
        return int(value)
    except Exception:
        return default


def _validate_runtime_profile(profile: dict[str, Any]) -> None:
    backend = str(profile.get("backend", "sqlite")).lower()
    if backend not in {"postgres", "postgresql", "pg"}:
        return

    explicit_dsn = str(profile.get("postgres_dsn", "")).strip()
    if explicit_dsn and not _is_placeholder(explicit_dsn):
        return

    pg = profile.get("postgres", {}) if isinstance(profile.get("postgres"), dict) else {}
    host = str(pg.get("host", "")).strip()
    database = str(pg.get("database", "")).strip()
    user = str(pg.get("user", "")).strip()
    password = str(pg.get("password", "")).strip()

    if _is_placeholder(host) or _is_placeholder(database) or _is_placeholder(user) or _is_placeholder(password):
        raise ValueError(
            "PostgreSQL 런타임 설정이 유효하지 않습니다. "
            "AGENT_POSTGRES_DSN 또는 postgres(host/database/user/password)를 실제 값으로 설정하세요."
        )


def load_runtime_profile() -> dict[str, Any]:
    load_env_candidates()
    if not CONFIG_PATH.exists():
        return {
            "name": "selfhost_simple",
            "backend": "sqlite",
            "sqlite_path": str(ROOT / "data" / "app.sqlite"),
            "service_base_url": "",
            "postgres_dsn": "",
            "postgres": {
                "host": "",
                "port": 5432,
                "database": "",
                "user": "",
                "password": "",
                "sslmode": "disable",
            },
            "langfuse": {
                "host": "",
                "public_key": "",
                "secret_key": "",
                "environment": "",
            },
            "llm": {
                "comparison_models": [],
                "prompt_review_model": "",
                "temperature": 0.2,
                "max_workers": 3,
                "timeout_sec": 25.0,
                "max_retries": 2,
                "openrouter_base_url": "https://openrouter.ai/api/v1",
            },
            "services": {},
        }

    payload = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
    default_profile = payload.get("default_profile", "selfhost_simple")
    selected = os.getenv("AGENT_PROFILE", default_profile)
    profiles = payload.get("profiles", {})
    profile = dict(profiles.get(selected, profiles.get(default_profile, {})))

    profile["name"] = selected
    profile.setdefault("backend", "sqlite")
    profile.setdefault("sqlite_path", "data/app.sqlite")
    profile.setdefault("service_base_url", "")
    profile.setdefault("postgres_dsn", "")
    profile.setdefault(
        "postgres",
        {
            "host": "",
            "port": 5432,
            "database": "",
            "user": "",
            "password": "",
            "sslmode": "disable",
        },
    )
    profile.setdefault(
        "langfuse",
        {
            "host": "",
            "public_key": "",
            "secret_key": "",
            "environment": "",
        },
    )
    llm_defaults = {
        "comparison_models": [],
        "prompt_review_model": "",
        "temperature": 0.2,
        "max_workers": 3,
        "timeout_sec": 25.0,
        "max_retries": 2,
        "openrouter_base_url": "https://openrouter.ai/api/v1",
    }
    llm_from_profile = profile.get("llm", {}) if isinstance(profile.get("llm"), dict) else {}
    profile["llm"] = {**llm_defaults, **llm_from_profile}
    profile.setdefault("services", {})

    env_base = os.getenv("AGENT_SERVICE_BASE_URL", "").strip()
    if env_base:
        profile["service_base_url"] = env_base

    env_dsn = os.getenv("AGENT_POSTGRES_DSN", "").strip() or os.getenv("DATABASE_URL", "").strip()
    if env_dsn:
        profile["postgres_dsn"] = env_dsn

    llm_env_models = (
        os.getenv("AGENT_LLM_COMPARISON_MODELS", "").strip()
        or os.getenv("AGENT_MODEL_SPECS", "").strip()
        or os.getenv("AGENT_OPENROUTER_MODELS", "").strip()
    )
    if llm_env_models:
        profile["llm"]["comparison_models"] = [value.strip() for value in llm_env_models.split(",") if value.strip()]

    env_prompt_review = os.getenv("AGENT_PROMPT_REVIEW_MODEL", "").strip()
    if env_prompt_review:
        profile["llm"]["prompt_review_model"] = env_prompt_review

    env_temperature = os.getenv("AGENT_LLM_TEMPERATURE", "").strip()
    if env_temperature:
        profile["llm"]["temperature"] = _safe_float(env_temperature, profile["llm"]["temperature"])

    env_max_workers = os.getenv("AGENT_LLM_MAX_WORKERS", "").strip()
    if env_max_workers:
        profile["llm"]["max_workers"] = max(1, _safe_int(env_max_workers, profile["llm"]["max_workers"]))

    env_timeout = os.getenv("AGENT_LLM_TIMEOUT_SEC", "").strip()
    if env_timeout:
        profile["llm"]["timeout_sec"] = max(1.0, _safe_float(env_timeout, profile["llm"]["timeout_sec"]))

    env_max_retries = os.getenv("AGENT_LLM_MAX_RETRIES", "").strip()
    if env_max_retries:
        profile["llm"]["max_retries"] = max(1, _safe_int(env_max_retries, profile["llm"]["max_retries"]))

    env_openrouter_base = os.getenv("AGENT_OPENROUTER_BASE_URL", "").strip() or os.getenv("OPENROUTER_BASE_URL", "").strip()
    if env_openrouter_base:
        profile["llm"]["openrouter_base_url"] = env_openrouter_base

    sqlite_path = Path(str(profile["sqlite_path"]))
    if not sqlite_path.is_absolute():
        sqlite_path = ROOT / sqlite_path
    profile["sqlite_path"] = str(sqlite_path)
    _validate_runtime_profile(profile)
    return profile


def resolve_service_url(profile: dict[str, Any], service_key: str) -> str:
    services = profile.get("services", {}) if isinstance(profile.get("services"), dict) else {}
    raw = str(services.get(service_key, "")).strip()
    if not raw:
        return ""
    if raw.startswith("http://") or raw.startswith("https://"):
        return raw
    base = str(profile.get("service_base_url", "")).rstrip("/")
    if not base:
        return ""
    return f"{base}/{raw.lstrip('/')}"


def resolve_postgres_dsn(profile: dict[str, Any]) -> str:
    explicit = str(profile.get("postgres_dsn", "")).strip()
    if explicit and not _is_placeholder(explicit):
        return explicit

    pg = profile.get("postgres", {}) if isinstance(profile.get("postgres"), dict) else {}
    host = str(pg.get("host", "")).strip()
    port = int(pg.get("port", 5432))
    database = str(pg.get("database", "")).strip()
    user = str(pg.get("user", "")).strip()
    password = str(pg.get("password", "")).strip()
    sslmode = str(pg.get("sslmode", "disable"))
    if _is_placeholder(host) or _is_placeholder(database) or _is_placeholder(user) or _is_placeholder(password):
        raise ValueError(
            "PostgreSQL DSN을 만들 수 없습니다. "
            "AGENT_POSTGRES_DSN 또는 postgres(host/database/user/password) 실값이 필요합니다."
        )
    user_q = quote_plus(user)
    password_q = quote_plus(password)
    return f"postgresql://{user_q}:{password_q}@{host}:{port}/{database}?sslmode={sslmode}"
