from typing import Any, Dict, Optional, Union
import json
import logging
logger = logging.getLogger(__name__)
class SettingsManager:
    """
    Manages application settings using a MySQL Key-Value table.
    Replaces JSON file storage.
    Table Schema Assumption:
    CREATE TABLE app_settings (
        profile_id CHAR(36),
        setting_key VARCHAR(100),
        setting_value TEXT,
        setting_type VARCHAR(20), -- 'str', 'int', 'float', 'bool', 'json'
        PRIMARY KEY (profile_id, setting_key)
    );
    """
    def __init__(self, data_manager):
        self.db: Any = data_manager.db
        self.profile_id = data_manager.profile_id
        self._cache: Dict[str, Any] = {}
        self._load_all_settings()
    def _load_all_settings(self):
        """Loads all settings for the current profile into memory."""
        query = "SELECT setting_key, setting_value, setting_type FROM app_settings WHERE profile_id = %s"
        rows = self.db.fetch_all(query, (self.profile_id,))
        self._cache = {}
        for row in rows:
            key = row['setting_key']
            raw_val = row['setting_value']
            val_type = row['setting_type']
            self._cache[key] = self._cast_value(raw_val, val_type)
        defaults = {
            "language": "TR",
            "display_currency": "TRY",
            "theme_name": "Green Harmony",
            "tab_position": "Sol",
            "password_enabled": False,
            "employees": {} # Complex types handled as JSON
        }
        for k, v in defaults.items():
            if k not in self._cache:
                self.set_setting(k, v)
    def _cast_value(self, value: str, type_str: str) -> Any:
        """Converts stored string back to Python type."""
        try:
            if type_str == 'int': return int(value)
            if type_str == 'float': return float(value)
            if type_str == 'bool': return value == '1'
            if type_str == 'json': return json.loads(value)
            return value # str
        except Exception as e:
            logger.error(f"Error casting setting value '{value}' to {type_str}: {e}")
            return value
    def _get_type_str(self, value: Any) -> str:
        """Determines the storage type string."""
        if isinstance(value, bool): return 'bool'
        if isinstance(value, int): return 'int'
        if isinstance(value, float): return 'float'
        if isinstance(value, (dict, list)): return 'json'
        return 'str'
    def get_setting(self, key: str, default: Any = None) -> Any:
        """
        Retrieves a setting value.
        Returns cached value if present, otherwise default.
        """
        return self._cache.get(key, default)
    def set_setting(self, key: str, value: Any) -> None:
        """
        Saves a setting to the database and updates cache.
        Handles atomic UPSERT (Insert or Update).
        """
        type_str = self._get_type_str(value)
        if type_str == 'bool':
            store_val = '1' if value else '0'
        elif type_str == 'json':
            store_val = json.dumps(value, ensure_ascii=False)
        else:
            store_val = str(value)
        query = """
            INSERT INTO app_settings (profile_id, setting_key, setting_value, setting_type)
            VALUES (%s, %s, %s, %s)
            ON DUPLICATE KEY UPDATE
                setting_value = VALUES(setting_value),
                setting_type = VALUES(setting_type)
        """
        try:
            self.db.execute_non_query(query, (self.profile_id, key, store_val, type_str))
            self._cache[key] = value # Update memory only on DB success
        except Exception as e:
            logger.error(f"Failed to save setting {key}: {e}")
            raise
    def get_employees(self) -> Dict[str, Any]:
        """Returns the employees dict."""
        return self.get_setting("employees", {})
    def add_employee(self, emp_id: str, data: Dict[str, Any]):
        """Adds or updates an employee within the JSON blob."""
        emps = self.get_employees()
        emps[emp_id] = data
        self.set_setting("employees", emps)
    def delete_employee(self, emp_id: str):
        """Removes an employee from the JSON blob."""
        emps = self.get_employees()
        if emp_id in emps:
            del emps[emp_id]
            self.set_setting("employees", emps)




