import { defineStore } from "pinia";
import { fetchProfilePreferences } from "../api/modules";

export type ThemeMode = "SYSTEM" | "LIGHT" | "DARK";
export type DensityMode = "COMFORTABLE" | "COMPACT";
export type ThemeScheme = "SLATE" | "OCEAN" | "FOREST" | "GRAPHITE" | "AMBER" | "RUBY" | "MIST" | "SAGE" | "DAWN";

type AppearancePayload = {
  themeMode?: unknown;
  density?: unknown;
  themeScheme?: unknown;
};

type AppearanceState = {
  themeMode: ThemeMode;
  density: DensityMode;
  themeScheme: ThemeScheme;
  initialized: boolean;
  bootstrapped: boolean;
};

const THEME_STORAGE_KEY = "themeMode";
const DENSITY_STORAGE_KEY = "density";
const THEME_SCHEME_STORAGE_KEY = "themeScheme";
const APPEARANCE_STORAGE_KEY = "appearance";
const APP_BOOT_OVERLAY_ID = "app-boot-overlay";

let mediaQuery: MediaQueryList | null = null;
let mediaListenerBound = false;
let authSyncListenerBound = false;
let currentStore: ReturnType<typeof useAppearanceStore> | null = null;

export const normalizeThemeMode = (raw: unknown): ThemeMode => {
  const value = String(raw || "").trim().toUpperCase();
  if (value === "LIGHT" || value === "DARK" || value === "SYSTEM") {
    return value;
  }
  return "SYSTEM";
};

export const normalizeDensity = (raw: unknown): DensityMode => {
  const value = String(raw || "").trim().toUpperCase();
  if (value === "COMPACT" || value === "COMFORTABLE") {
    return value;
  }
  return "COMFORTABLE";
};

export const normalizeThemeScheme = (raw: unknown): ThemeScheme => {
  const value = String(raw || "").trim().toUpperCase();
  if (
    value === "SLATE" ||
    value === "OCEAN" ||
    value === "FOREST" ||
    value === "GRAPHITE" ||
    value === "AMBER" ||
    value === "RUBY" ||
    value === "MIST" ||
    value === "SAGE" ||
    value === "DAWN"
  ) {
    return value;
  }
  return "SLATE";
};

const readStoredAppearance = (): { themeMode?: string; density?: string; themeScheme?: string } => {
  const raw = localStorage.getItem(APPEARANCE_STORAGE_KEY);
  if (!raw) {
    return {
      themeMode: String(localStorage.getItem(THEME_STORAGE_KEY) || "").trim(),
      density: String(localStorage.getItem(DENSITY_STORAGE_KEY) || "").trim(),
      themeScheme: String(localStorage.getItem(THEME_SCHEME_STORAGE_KEY) || "").trim(),
    };
  }
  try {
    const parsed = JSON.parse(raw) || {};
    return {
      themeMode: String(parsed?.themeMode || localStorage.getItem(THEME_STORAGE_KEY) || "").trim(),
      density: String(parsed?.density || localStorage.getItem(DENSITY_STORAGE_KEY) || "").trim(),
      themeScheme: String(parsed?.themeScheme || localStorage.getItem(THEME_SCHEME_STORAGE_KEY) || "").trim(),
    };
  } catch (_e) {
    return {
      themeMode: String(localStorage.getItem(THEME_STORAGE_KEY) || "").trim(),
      density: String(localStorage.getItem(DENSITY_STORAGE_KEY) || "").trim(),
      themeScheme: String(localStorage.getItem(THEME_SCHEME_STORAGE_KEY) || "").trim(),
    };
  }
};

const persistAppearance = (state: AppearanceState) => {
  localStorage.setItem(THEME_STORAGE_KEY, state.themeMode);
  localStorage.setItem(DENSITY_STORAGE_KEY, state.density);
  localStorage.setItem(THEME_SCHEME_STORAGE_KEY, state.themeScheme);
  localStorage.setItem(
    APPEARANCE_STORAGE_KEY,
    JSON.stringify({ themeMode: state.themeMode, density: state.density, themeScheme: state.themeScheme }),
  );
};

const resolveThemeMode = (themeMode: ThemeMode): "light" | "dark" => {
  if (themeMode === "LIGHT") {
    return "light";
  }
  if (themeMode === "DARK") {
    return "dark";
  }
  return mediaQuery?.matches ? "dark" : "light";
};

const applyAppearanceToDocument = (state: AppearanceState) => {
  const root = document.documentElement;
  const resolvedTheme = resolveThemeMode(state.themeMode);
  root.dataset.themeMode = resolvedTheme;
  root.dataset.themePreference = state.themeMode.toLowerCase();
  root.dataset.density = state.density.toLowerCase();
  root.dataset.themeScheme = state.themeScheme.toLowerCase();
  root.classList.toggle("dark", resolvedTheme === "dark");
};

const removeBootOverlay = () => {
  if (typeof document === "undefined") {
    return;
  }
  const overlay = document.getElementById(APP_BOOT_OVERLAY_ID);
  if (!overlay) {
    return;
  }
  overlay.classList.add("is-leaving");
  window.setTimeout(() => {
    overlay.remove();
  }, 320);
};

const handleSystemThemeChange = () => {
  if (currentStore?.themeMode === "SYSTEM") {
    currentStore.applyToDocument();
  }
};

const handleAuthTokenUpdated = () => {
  currentStore?.syncFromStorage();
};

const ensureSystemThemeListener = () => {
  if (typeof window === "undefined") {
    return;
  }
  if (!mediaQuery) {
    mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
  }
  if (mediaQuery && !mediaListenerBound) {
    if (typeof mediaQuery.addEventListener === "function") {
      mediaQuery.addEventListener("change", handleSystemThemeChange);
    } else if (typeof mediaQuery.addListener === "function") {
      mediaQuery.addListener(handleSystemThemeChange);
    }
    mediaListenerBound = true;
  }
};

const ensureAuthSyncListener = () => {
  if (typeof window === "undefined" || authSyncListenerBound) {
    return;
  }
  window.addEventListener("auth:token-updated", handleAuthTokenUpdated as EventListener);
  authSyncListenerBound = true;
};

export const useAppearanceStore = defineStore("appearance", {
  state: (): AppearanceState => ({
    themeMode: "SYSTEM",
    density: "COMFORTABLE",
    themeScheme: "SLATE",
    initialized: false,
    bootstrapped: false,
  }),
  getters: {
    elementPlusSize: (state): "small" | "default" => (state.density === "COMPACT" ? "small" : "default"),
    isBootstrapped: (state): boolean => state.bootstrapped,
  },
  actions: {
    initAppearance() {
      currentStore = this;
      ensureSystemThemeListener();
      ensureAuthSyncListener();
      this.syncFromStorage();
    },
    applyToDocument() {
      applyAppearanceToDocument(this);
    },
    setAppearance(payload: AppearancePayload, persist = true) {
      this.themeMode = normalizeThemeMode(payload?.themeMode ?? this.themeMode);
      this.density = normalizeDensity(payload?.density ?? this.density);
      this.themeScheme = normalizeThemeScheme(payload?.themeScheme ?? this.themeScheme);
      this.initialized = true;
      if (persist) {
        persistAppearance(this);
      }
      this.applyToDocument();
    },
    syncFromStorage() {
      const stored = readStoredAppearance();
      this.setAppearance(
        {
          themeMode: stored.themeMode,
          density: stored.density,
          themeScheme: stored.themeScheme,
        },
        true,
      );
    },
    async syncFromServer() {
      if (!String(localStorage.getItem("token") || "").trim()) {
        return;
      }
      try {
        const resp = await fetchProfilePreferences();
        const appearance = resp?.data || {};
        this.setAppearance(
          {
            themeMode: appearance?.themeMode,
            density: appearance?.density,
            themeScheme: appearance?.themeScheme,
          },
          true,
        );
      } catch (_e) {
        // Keep local preferences on sync failure.
      }
    },
    markBootstrapped() {
      if (this.bootstrapped) {
        return;
      }
      this.bootstrapped = true;
      removeBootOverlay();
    },
  },
});
