"use client";
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import type { AppSettings } from "@/lib/db/appSettings";
import { setBoolSetting, setNumberSetting, setColorSetting, setPaginationMode } from "@/app/actions/settings";

type BoolKey = "fadeTransitions" | "purgeFilesOnDelete" | "useRecycleBin";
type NumKey = "fadeDurationMs" | "trashRetentionDays" | "gridColumns" | "gridColumnsPortrait" | "supersededRetentionDays" | "coverPageSize";
type ColorKey = "accentPrimary" | "accentSecondary";
type PaginationModeKey = "paginationMode";

interface Ctx {
  settings: AppSettings;
  set(key: BoolKey, value: boolean): void;
  set(key: NumKey, value: number): void;
  set(key: ColorKey, value: string): void;
  set(key: PaginationModeKey, value: AppSettings["paginationMode"]): void;
}

const SettingsCtx = createContext<Ctx | null>(null);

const NUM_KEYS = new Set<string>(["fadeDurationMs", "trashRetentionDays", "gridColumns", "gridColumnsPortrait", "supersededRetentionDays", "coverPageSize"]);
const COLOR_KEYS = new Set<string>(["accentPrimary", "accentSecondary"]);
const PAGINATION_MODE_KEYS = new Set<string>(["paginationMode"]);

const ACCENT_VARS: Record<ColorKey, [string, string]> = {
  accentPrimary: ["--color-cyan", "--color-cyan-glow"],
  accentSecondary: ["--color-violet", "--color-violet-glow"],
};

export function SettingsProvider({
  initial,
  children,
}: {
  initial: AppSettings;
  children: React.ReactNode;
}) {
  const [settings, setSettings] = useState<AppSettings>(initial);

  // The server is the source of truth, but the parent layout passes the latest
  // server values on every render. Keep our state in sync after server mutations.
  useEffect(() => {
    setSettings(initial);
  }, [initial]);

  useEffect(() => {
    document.documentElement.dataset.fade = settings.fadeTransitions ? "on" : "off";
    document.documentElement.style.setProperty("--fade-duration", `${settings.fadeDurationMs}ms`);
  }, [settings.fadeTransitions, settings.fadeDurationMs]);

  useEffect(() => {
    const n = Math.max(2, Math.min(4, settings.gridColumns || 3));
    document.documentElement.style.setProperty("--grid-cols", String(n));
  }, [settings.gridColumns]);

  useEffect(() => {
    const n = Math.max(4, Math.min(10, settings.gridColumnsPortrait || 6));
    document.documentElement.style.setProperty("--grid-cols-portrait", String(n));
  }, [settings.gridColumnsPortrait]);

  useEffect(() => {
    const root = document.documentElement;
    for (const [key, [base, glow]] of Object.entries(ACCENT_VARS) as [ColorKey, [string, string]][]) {
      const value = settings[key];
      if (value) {
        root.style.setProperty(base, value);
        root.style.setProperty(glow, value);
      } else {
        root.style.removeProperty(base);
        root.style.removeProperty(glow);
      }
    }
  }, [settings.accentPrimary, settings.accentSecondary]);

  const set = useCallback((key: BoolKey | NumKey | ColorKey | PaginationModeKey, value: boolean | number | string) => {
    setSettings((cur) => ({ ...cur, [key]: value }));
    if (NUM_KEYS.has(key)) {
      void setNumberSetting(key as NumKey, value as number);
    } else if (COLOR_KEYS.has(key)) {
      void setColorSetting(key as ColorKey, value as string);
    } else if (PAGINATION_MODE_KEYS.has(key)) {
      void setPaginationMode(value as AppSettings["paginationMode"]);
    } else {
      void setBoolSetting(key as BoolKey, value as boolean);
    }
  }, []) as Ctx["set"];

  const value = useMemo<Ctx>(() => ({ settings, set }), [settings, set]);
  return <SettingsCtx.Provider value={value}>{children}</SettingsCtx.Provider>;
}

export function useSettings() {
  const ctx = useContext(SettingsCtx);
  if (!ctx) throw new Error("useSettings must be used within SettingsProvider");
  return ctx;
}
