"""
Configuration Manager Module.
=============================

Singleton class to manage loading and saving application settings to a JSON file.
Ensures robustness by merging with defaults and handling file paths correctly.
"""

import json
import logging
from pathlib import Path
from typing import Any, Dict

from src.core.paths import get_base_path

# Default Configuration
DEFAULT_SETTINGS = {
    "hotkey": "f8",
    "hotkey_translate": "f10",
    "hotkey_correct": "f9",     # New: Transcribe + Correct
    "model_size": "small",
    "input_device": None,       # Device ID (int) or Name (str), None = Default
    "save_recordings": False,   # Save .wav files for debugging
    "silence_threshold": 0.02,  # Amplitude threshold (0.0 - 1.0)
    "silence_duration": 1.0,    # Seconds of silence to trigger auto-submit
    "visualizer_style": "line", # 'bar' or 'line'
    "opacity": 1.0,             # Window opacity (0.1 - 1.0)
    "ui_scale": 1.0,            # Global UI Scale (0.75 - 1.5)
    "always_on_top": True,
    "run_on_startup": False,    # (Placeholder)
    
    # Window Position
    "overlay_position": "Bottom Center", 
    "overlay_offset_x": 0,
    "overlay_offset_y": 0,
    
    # Input
    "input_method": "Clipboard Paste", # "Clipboard Paste" or "Simulate Typing"
    "typing_speed": 100,               # CPM (Chars Per Minute) if typing
    
    # AI - Advanced
    "language": "auto",         # "auto" or ISO code
    "task": "transcribe",       # "transcribe" or "translate" (to English)
    "compute_device": "auto",   # "auto", "cuda", "cpu"
    "compute_type": "int8",     # "int8", "float16", "float32"
    "beam_size": 5,
    "best_of": 5,
    "vad_filter": True,
    "no_repeat_ngram_size": 0,
    "condition_on_previous_text": True,
    "initial_prompt": "Mm-hmm. Okay, let's go. I speak in full sentences.", # Default: Forces punctuation
    
    # LLM Correction
    "llm_enabled": False,
    "llm_mode": "Standard", # "Grammar", "Standard", "Rewrite"
    "llm_model_name": "llama-3.2-1b-instruct",
    

    
    # Low VRAM Mode
    "unload_models_after_use": False # If True, models are unloaded immediately to free VRAM
}

class ConfigManager:
    """
    Singleton Configuration Manager.
    """
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(ConfigManager, cls).__new__(cls)
            cls._instance._init()
        return cls._instance

    def _init(self):
        """Initialize the config manager (called only once)."""
        self.base_path = get_base_path()
        self.config_file = self.base_path / "settings.json"
        self.data = DEFAULT_SETTINGS.copy()
        self.load()

    def load(self):
        """Load settings from JSON file, merging with defaults."""
        if self.config_file.exists():
            try:
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    loaded = json.load(f)
                    
                    # Merge loaded data into defaults (preserves new default keys)
                    for key, value in loaded.items():
                        if key in DEFAULT_SETTINGS:
                            self.data[key] = value
                            
                logging.info(f"Settings loaded from {self.config_file}")
            except Exception as e:
                logging.error(f"Failed to load settings: {e}")
        else:
            logging.info("No settings file found. Using defaults.")
            self.save()

    def save(self):
        """Save current settings to JSON file."""
        try:
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(self.data, f, indent=4)
            logging.info("Settings saved.")
        except Exception as e:
            logging.error(f"Failed to save settings: {e}")

    def get(self, key: str, default: Any = None) -> Any:
        """Get a setting value."""
        return self.data.get(key, DEFAULT_SETTINGS.get(key, default))



    def set(self, key: str, value: Any):
        """Set a setting value and save."""
        if self.data.get(key) != value:
            self.data[key] = value
            self.save()

    def set_bulk(self, updates: Dict[str, Any]):
        """Update multiple keys and save once."""
        changed = False
        for k, v in updates.items():
            if self.data.get(k) != v:
                self.data[k] = v
                changed = True
        if changed:
            self.save()
