use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;
use tauri::{AppHandle, Manager};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AppSettings {
    pub theme: String,
    pub default_shell: Option<String>,
    pub vigthoria_cli_path: Option<String>,
    pub show_report_panel: bool,
    pub last_workspace_id: Option<String>,
    #[serde(default = "default_hyperloop_url")]
    pub hyperloop_url: String,
    #[serde(default = "default_template_url")]
    pub template_url: String,
    #[serde(default)]
    pub comfort_prompt_enabled: bool,
    #[serde(default = "default_goa_auto_route")]
    pub goa_auto_route: bool,
    #[serde(default = "default_tools_tab")]
    pub tools_tab: String,
}

fn default_hyperloop_url() -> String {
    "https://hyperloop.vigthoria.io".into()
}

fn default_template_url() -> String {
    "https://templates.vigthoria.io".into()
}

fn default_tools_tab() -> String {
    "report".into()
}

fn default_goa_auto_route() -> bool {
    true
}

impl Default for AppSettings {
    fn default() -> Self {
        Self {
            theme: "vigthoria-dark".into(),
            default_shell: None,
            vigthoria_cli_path: None,
            show_report_panel: true,
            last_workspace_id: None,
            hyperloop_url: default_hyperloop_url(),
            template_url: default_template_url(),
            comfort_prompt_enabled: true,
            goa_auto_route: default_goa_auto_route(),
            tools_tab: default_tools_tab(),
        }
    }
}

pub struct SettingsStore {
    inner: parking_lot::Mutex<AppSettings>,
}

impl Default for SettingsStore {
    fn default() -> Self {
        Self {
            inner: parking_lot::Mutex::new(AppSettings::default()),
        }
    }
}

impl SettingsStore {
    pub fn load_from_disk(&self, app: &AppHandle) {
        let path = settings_path(app);
        if let Ok(raw) = fs::read_to_string(path) {
            if let Ok(parsed) = serde_json::from_str::<AppSettings>(&raw) {
                *self.inner.lock() = parsed;
            }
        }
    }

    pub fn get(&self) -> AppSettings {
        self.inner.lock().clone()
    }

    pub fn save(&self, app: &AppHandle, settings: AppSettings) -> Result<AppSettings, String> {
        *self.inner.lock() = settings.clone();
        self.persist(app)?;
        Ok(settings)
    }

    pub fn persist(&self, app: &AppHandle) -> Result<(), String> {
        let path = settings_path(app);
        if let Some(parent) = path.parent() {
            fs::create_dir_all(parent).map_err(|e| e.to_string())?;
        }
        let json = serde_json::to_string_pretty(&*self.inner.lock()).map_err(|e| e.to_string())?;
        fs::write(path, json).map_err(|e| e.to_string())?;
        Ok(())
    }
}

fn settings_path(app: &AppHandle) -> PathBuf {
    app.path()
        .app_data_dir()
        .unwrap_or_else(|_| PathBuf::from("."))
        .join("settings.json")
}
