//! 应用设置：本地 JSON 持久化（MVP；token 后续迁系统钥匙串）。

use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use tauri::Manager;

#[derive(Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Settings {
    pub hotkey: String,
    pub mic: String,
    pub sound: bool,
    pub autostart: bool,
    pub theme: String,
    pub server_url: String,
    pub token: String,
    pub device_id: String,
    /// 首次启动引导是否已完成（11F）。
    pub onboarding_done: bool,
}

impl Default for Settings {
    fn default() -> Self {
        Self {
            hotkey: "CmdOrCtrl+Shift+Space".into(),
            mic: String::new(),
            sound: false,
            autostart: true,
            theme: "system".into(),
            server_url: "http://localhost:8080".into(),
            token: String::new(),
            device_id: uuid::Uuid::new_v4().to_string(),
            onboarding_done: false,
        }
    }
}

pub struct SettingsStore {
    path: PathBuf,
    pub current: Mutex<Settings>,
}

impl SettingsStore {
    pub fn load(app: &tauri::AppHandle) -> Self {
        let dir = app
            .path()
            .app_config_dir()
            .unwrap_or_else(|_| std::env::temp_dir());
        let _ = std::fs::create_dir_all(&dir);
        let path = dir.join("settings.json");
        let current = std::fs::read(&path)
            .ok()
            .and_then(|b| serde_json::from_slice(&b).ok())
            .unwrap_or_default();
        let store = Self {
            path,
            current: Mutex::new(current),
        };
        store.save(); // 首次生成 device_id 后立即落盘
        store
    }

    pub fn save(&self) {
        let s = self.current.lock().clone();
        if let Ok(b) = serde_json::to_vec_pretty(&s) {
            let _ = std::fs::write(&self.path, b);
        }
    }

    pub fn get(&self) -> Settings {
        self.current.lock().clone()
    }

    pub fn set(&self, s: Settings) {
        *self.current.lock() = s;
        self.save();
    }
}

#[tauri::command]
pub fn get_settings(store: tauri::State<SettingsStore>) -> Settings {
    store.get()
}

#[tauri::command]
pub fn set_settings(store: tauri::State<SettingsStore>, settings: Settings) {
    store.set(settings);
}

#[tauri::command]
pub fn list_mic_devices() -> Vec<String> {
    crate::audio::list_devices()
}
