from pathlib import Path

import config
from config import Settings

ENV_PATH = config.ROOT_DIR / ".env"

DEFAULTS = {
    "DEEPSEEK_API_KEY": "sk-your-key-here",
    "DEEPSEEK_MODEL": "deepseek-chat",
    "SYSTEM_PROMPT": "你是一个友好、专业的AI助手。",
    "MAX_HISTORY_TURNS": "20",
    "MAX_TOKENS": "4096",
    "WEB_SEARCH_ENABLED": "false",
    "DASHSCOPE_API_KEY": "sk-your-dashscope-key",
    "TTS_MODEL": "cosyvoice-v3-flash",
    "TTS_VOICE": "longanyang",
}


def _quote_env_value(value: str) -> str:
    if not value:
        return '""'
    if any(c in value for c in " #\t\r\n\"'="):
        escaped = value.replace("\\", "\\\\").replace('"', '\\"')
        return f'"{escaped}"'
    return value


def mask_api_key(key: str) -> str:
    if not key or key in ("sk-your-key-here", "sk-your-dashscope-key"):
        return ""
    if len(key) <= 8:
        return "sk-****"
    return f"{key[:3]}****{key[-4:]}"


def read_env_file() -> dict[str, str]:
    if not ENV_PATH.exists():
        return {}
    result: dict[str, str] = {}
    for line in ENV_PATH.read_text(encoding="utf-8").splitlines():
        line = line.strip()
        if not line or line.startswith("#") or "=" not in line:
            continue
        key, _, value = line.partition("=")
        key = key.strip()
        value = value.strip()
        if value.startswith('"') and value.endswith('"'):
            value = value[1:-1].replace('\\"', '"').replace("\\\\", "\\")
        result[key] = value
    return result


def write_env_file(updates: dict[str, str]) -> None:
    existing = read_env_file()
    existing.update(updates)
    merged = {**DEFAULTS, **existing}
    lines: list[str] = []
    for key in DEFAULTS:
        lines.append(f"{key}={_quote_env_value(merged[key])}")
    for key, value in merged.items():
        if key not in DEFAULTS:
            lines.append(f"{key}={_quote_env_value(value)}")
    ENV_PATH.parent.mkdir(parents=True, exist_ok=True)
    ENV_PATH.write_text("\n".join(lines) + "\n", encoding="utf-8")


def get_public_settings(settings: Settings) -> dict:
    key = settings.deepseek_api_key
    configured = bool(key and key != "sk-your-key-here")
    ds_key = settings.dashscope_api_key
    tts_configured = bool(ds_key and ds_key != "sk-your-dashscope-key")
    return {
        "api_key_configured": configured,
        "deepseek_api_key_masked": mask_api_key(key) if configured else "",
        "deepseek_model": settings.deepseek_model,
        "system_prompt": settings.system_prompt,
        "max_history_turns": settings.max_history_turns,
        "max_tokens": settings.max_tokens,
        "web_search_enabled": settings.web_search_enabled,
        "dashscope_api_key_configured": tts_configured,
        "dashscope_api_key_masked": mask_api_key(ds_key) if tts_configured else "",
        "tts_model": settings.tts_model,
        "tts_voice": settings.tts_voice,
    }


def apply_settings_update(data: dict) -> dict[str, str]:
    updates: dict[str, str] = {}
    if data.get("deepseek_api_key"):
        updates["DEEPSEEK_API_KEY"] = data["deepseek_api_key"].strip()
    if data.get("deepseek_model") is not None:
        updates["DEEPSEEK_MODEL"] = str(data["deepseek_model"]).strip()
    if data.get("system_prompt") is not None:
        updates["SYSTEM_PROMPT"] = str(data["system_prompt"]).strip()
    if data.get("max_history_turns") is not None:
        updates["MAX_HISTORY_TURNS"] = str(int(data["max_history_turns"]))
    if data.get("max_tokens") is not None:
        updates["MAX_TOKENS"] = str(int(data["max_tokens"]))
    if data.get("web_search_enabled") is not None:
        updates["WEB_SEARCH_ENABLED"] = "true" if data["web_search_enabled"] else "false"
    if data.get("dashscope_api_key"):
        updates["DASHSCOPE_API_KEY"] = data["dashscope_api_key"].strip()
    if data.get("tts_model") is not None:
        updates["TTS_MODEL"] = str(data["tts_model"]).strip()
    if data.get("tts_voice") is not None:
        updates["TTS_VOICE"] = str(data["tts_voice"]).strip()
    return updates
