import json
from dataclasses import asdict, dataclass

from .paths import config_path


@dataclass
class AppConfig:
    language: str = "uk"
    start_with_windows: bool = False
    close_behavior: str = "exit"
    show_tooltips: bool = True
    ptt_key: str = "F8"
    input_device: int = -1
    output_device: int = -1
    input_device_name: str = ""
    output_device_name: str = ""
    direct_voice_enabled: bool = True
    samplerate: int = 48000
    # Never ship a real key in source, portable builds, or installers.
    # Each user enters their own key on their own computer.
    api_key: str = ""
    source_language: str = "uk"
    target_language: str = "en"
    transcription_model: str = "gpt-4o-mini-transcribe"
    translation_model: str = "gpt-4o-mini"
    tts_model: str = "gpt-4o-mini-tts"
    tts_voice: str = "marin"
    update_manifest_url: str = ""
    output_mode: str = "Stereo"
    ptt_mode: str = "Утримувати для передачі"
    indicator_enabled: bool = True
    ptt_autostart: bool = True
    auto_update: bool = True
    update_channel: str = "Стабільний (Рекомендовано)"

    @classmethod
    def load(cls):
        path = config_path()
        if not path.exists():
            return cls()
        try:
            data = json.loads(path.read_text(encoding="utf-8"))
            allowed = asdict(cls())
            config = cls(**{key: data[key] for key in allowed if key in data})
            if str(config.ptt_key).strip().upper() in {"", "+", "NONE", "NULL"}:
                config.ptt_key = "F8"
            valid_voices = {
                "alloy", "ash", "ballad", "coral", "echo", "fable", "nova",
                "onyx", "sage", "shimmer", "verse", "marin", "cedar",
            }
            if config.tts_voice not in valid_voices:
                config.tts_voice = "marin"
            if config.output_mode not in {"Stereo", "Mono"}:
                config.output_mode = "Stereo"
            if config.ptt_mode not in {"Утримувати для передачі", "Перемикач"}:
                config.ptt_mode = "Утримувати для передачі"
            if int(config.samplerate) not in {16000, 44100, 48000}:
                config.samplerate = 48000
            config.save()
            return config
        except Exception:
            return cls()

    def save(self):
        path = config_path()
        path.parent.mkdir(parents=True, exist_ok=True)
        temporary = path.with_suffix(".tmp")
        temporary.write_text(json.dumps(asdict(self), ensure_ascii=False, indent=2), encoding="utf-8")
        temporary.replace(path)


def clear_saved_api_key() -> bool:
    """Clear only the saved API key while preserving every other setting.

    Used by a true first install. Updates keep the user's own locally saved key.
    Returns True when a settings file was changed.
    """
    path = config_path()
    if not path.exists():
        return False
    try:
        data = json.loads(path.read_text(encoding="utf-8"))
        if not isinstance(data, dict):
            return False
        changed = bool(str(data.get("api_key", "")).strip())
        data["api_key"] = ""
        temporary = path.with_suffix(".tmp")
        temporary.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
        temporary.replace(path)
        return changed
    except Exception:
        return False
