import { defineStore } from "pinia";
import { ref, watch } from "vue";
import { setLocale } from "@/utils/i18n";
import { invoke, isTauri } from "@tauri-apps/api/core";
import { ThemeMode, Language, type AppSettings, defaultSettings } from "@/types";

const isTauriBool = isTauri();

const log = (level: "debug" | "info" | "error", msg: string) => {
  import("@tauri-apps/plugin-log")
    .then(({ debug, info, error }) => {
      if (level === "debug") debug(msg);
      else if (level === "info") info(msg);
      else error(msg);
    })
    .catch(() => {
      console.log(`[${level}] ${msg}`);
    });
};

export const useSettingsStore = defineStore("settings", () => {
  const settings = ref<AppSettings>({ ...defaultSettings });
  const isLoaded = ref(false);

  let systemThemeListener: MediaQueryList | null = null;

  const setupSystemThemeListener = () => {
    if (typeof window !== "undefined") {
      systemThemeListener = window.matchMedia("(prefers-color-scheme: dark)");
      const handleSystemThemeChange = () => {
        if (settings.value.theme === ThemeMode.System) {
          if (isTauriBool) {
            log("info", "[systemThemeListener] System theme changed, reapplying");
          }
          applyTheme();
        }
      };
      systemThemeListener.addEventListener("change", handleSystemThemeChange);
    }
  };

  const applyTheme = () => {
    const theme = settings.value.theme;
    log("debug", `[applyTheme] Applying theme: ${theme}`);

    const body = document.body;
    const html = document.documentElement;

    body.classList.remove("light", "dark");
    html.classList.remove("light", "dark");
    body.removeAttribute("data-theme");
    html.removeAttribute("data-theme");

    let actualTheme: "light" | "dark" = "light";

    if (theme === ThemeMode.System) {
      const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
      actualTheme = prefersDark ? "dark" : "light";
    } else if (theme === ThemeMode.Dark) {
      actualTheme = "dark";
    }

    body.classList.add(actualTheme);
    html.classList.add(actualTheme);
    body.setAttribute("data-theme", actualTheme);
    html.setAttribute("data-theme", actualTheme);

    log("info", `[applyTheme] Theme applied: ${theme} -> ${actualTheme}`);
  };

  const applyFontSize = () => {
    const fontSize = settings.value.fontSize;
    log("debug", `[applyFontSize] Applying font size: ${fontSize}px`);
    document.documentElement.style.setProperty("--app-font-size", `${fontSize}px`);
    log("info", `[applyFontSize] Font size applied: ${fontSize}px`);
  };

  const applyLanguage = () => {
    const lang = settings.value.language;
    const langCode = lang === Language.ZhCN ? "zh" : "en";
    log("debug", `[applyLanguage] Applying language: ${lang}`);
    setLocale(langCode as "zh" | "en");
    log("info", `[applyLanguage] Language applied: ${lang}`);
  };

  const loadSettings = async () => {
    log("debug", "[loadSettings] Loading user settings");

    if (!isTauriBool) {
      log("debug", "[loadSettings] Non-Tauri, loading from localStorage");
      try {
        const savedSettings = localStorage.getItem("app-settings");
        if (savedSettings) {
          settings.value = { ...defaultSettings, ...JSON.parse(savedSettings) };
          log("debug", `[loadSettings] Loaded from localStorage: theme=${settings.value.theme}`);
        }
      } catch (err) {
        console.error("Failed to load settings from localStorage:", err);
      }
      isLoaded.value = true;
      applyTheme();
      applyFontSize();
      applyLanguage();
      setupSystemThemeListener();
      return;
    }

    try {
      log("debug", "[loadSettings] Tauri env, loading from backend");
      const userSettings = await invoke<AppSettings>("load_user_settings");
      if (userSettings) {
        settings.value = { ...defaultSettings, ...userSettings };
        log("debug", `[loadSettings] Loaded from backend: theme=${settings.value.theme}`);
      }
      isLoaded.value = true;
      applyTheme();
      applyFontSize();
      applyLanguage();
      setupSystemThemeListener();
    } catch (err) {
      log("error", `[loadSettings] Failed to load settings: ${err}`);
      settings.value = { ...defaultSettings };
      isLoaded.value = true;
      applyTheme();
      applyFontSize();
      applyLanguage();
      setupSystemThemeListener();
    }
  };

  const saveSettings = async () => {
    log("debug", `[saveSettings] Saving settings: theme=${settings.value.theme}`);

    if (!isTauriBool) {
      try {
        localStorage.setItem("app-settings", JSON.stringify(settings.value));
        log("debug", "[saveSettings] Saved to localStorage");
      } catch (err) {
        console.error("Failed to save settings to localStorage:", err);
      }
      return;
    }

    try {
      await invoke("save_user_settings", { settings: settings.value });
      log("debug", "[saveSettings] Saved to backend");
    } catch (err) {
      log("error", `[saveSettings] Failed to save settings: ${err}`);
    }
  };

  const updateSetting = async <K extends keyof AppSettings>(key: K, value: AppSettings[K]) => {
    settings.value[key] = value;
    await saveSettings();
  };

  const resetSettings = async () => {
    settings.value = { ...defaultSettings };
    await saveSettings();
  };

  watch(
    settings,
    () => {
      if (isLoaded.value) {
        saveSettings();
      }
    },
    { deep: true }
  );

  const setTheme = async (theme: ThemeMode) => {
    log("debug", `[setTheme] Setting theme: ${theme}`);
    await updateSetting("theme", theme);
    applyTheme();
  };

  const setLanguage = async (language: Language) => {
    log("debug", `[setLanguage] Setting language: ${language}`);
    await updateSetting("language", language);
    applyLanguage();
  };

  const setFontSize = async (fontSize: number) => {
    log("debug", `[setFontSize] Setting font size: ${fontSize}px`);
    await updateSetting("fontSize", fontSize);
    applyFontSize();
  };

  const setSidebarCollapsed = async (collapsed: boolean) => {
    await updateSetting("sidebarCollapsed", collapsed);
  };

  const setSidebarWidth = async (width: number) => {
    const clampedWidth = Math.max(200, Math.min(320, width));
    await updateSetting("sidebarWidth", clampedWidth);
  };

  const setSidebarPinned = async (pinned: boolean) => {
    await updateSetting("sidebarPinned", pinned);
  };

  return {
    settings,
    isLoaded,
    loadSettings,
    saveSettings,
    updateSetting,
    resetSettings,
    setTheme,
    setLanguage,
    setFontSize,
    setSidebarCollapsed,
    setSidebarWidth,
    setSidebarPinned,
    applyTheme,
    applyFontSize,
    applyLanguage
  };
});
