import { calculateBrightness, hexToOklch } from "@/lib/helpers/colorUtils";
import {
  hexToRgba,
  resolveBgType,
  normalizeBgNumber,
  PATTERN_BACKGROUND_OPACITY,
  PATTERN_VECTOR_OPACITY,
  PRIMARY_LIGHT_OPACITY,
  type BgType,
  type RestaurantBackgroundSettings,
} from "@/lib/helpers/backgroundUtils";
import type { AboutResponse } from "@/app/[name]/(Main)/about/types/Types";
import type {
  CategoriesResponse,
  FoodsResponse,
} from "@/app/[name]/(Main)/types/Types";
import type { QueryClient } from "@tanstack/react-query";

export type CachedRestaurantTheme = {
  version: 1;
  menuColor: string;
  bgType?: BgType;
  bgUrl?: string | null;
  bgBlur?: number | null;
  bgOpacity?: number | null;
  bgOverlay?: string | null;
  isPattern: boolean;
  patternDataUrl?: string | null;
  primaryOklch?: string;
  primaryForeground?: string;
  backgroundTint?: string;
  bgPatternVector?: string;
  primaryLight?: string;
};

const CACHE_VERSION = 1;
const CACHE_KEY_PREFIX = "restaurant-theme";
const LEGACY_COLOR_KEY = "theme-primary-color";
const ABOUT_CACHE_PREFIX = "restaurant-about";
const MENU_CACHE_PREFIX = "restaurant-menu";
const CATEGORIES_CACHE_PREFIX = "restaurant-categories";
export const THEME_BG_ELEMENT_ID = "cached-theme-bg";
const THEME_BG_IMG_ID = "cached-theme-bg-img";
const THEME_BG_OVERLAY_ID = "cached-theme-bg-overlay";
const PREFERENCE_STORAGE_KEY = "preference-storage";

export function isNightModeEnabled(): boolean {
  if (typeof window === "undefined") return false;

  try {
    const raw = localStorage.getItem(PREFERENCE_STORAGE_KEY);
    if (!raw) return false;
    const parsed = JSON.parse(raw) as {
      state?: { items?: Record<string, { value?: unknown }> };
    };
    return parsed?.state?.items?.["night-mode"]?.value === true;
  } catch {
    return false;
  }
}

export function clearRestaurantBackgroundOverrides(): void {
  if (typeof document === "undefined") return;

  const root = document.documentElement;
  root.removeAttribute("data-pattern-bg");
  root.removeAttribute("data-image-bg");
  root.style.removeProperty("--background");
  root.style.removeProperty("--bg-pattern-base");
  root.style.removeProperty("--bg-pattern-vector");
  root.style.removeProperty("--primary-light");
  document.getElementById(THEME_BG_ELEMENT_ID)?.remove();
}

export function getThemeCacheKey(slug: string): string {
  return `${CACHE_KEY_PREFIX}:${slug}`;
}

export function getAboutCacheKey(slug: string): string {
  return `${ABOUT_CACHE_PREFIX}:${slug}`;
}

export function getMenuCacheKey(slug: string): string {
  return `${MENU_CACHE_PREFIX}:${slug}`;
}

export function getCategoriesCacheKey(slug: string): string {
  return `${CATEGORIES_CACHE_PREFIX}:${slug}`;
}

export function getRestaurantSlugFromPath(pathname?: string): string | null {
  const path =
    pathname ?? (typeof window !== "undefined" ? window.location.pathname : "");
  const segment = path.split("/").filter(Boolean)[0];
  if (!segment || segment === "auth") return null;
  return segment;
}

export function computeThemeCssValues(menuColor: string) {
  const primaryOklch = hexToOklch(menuColor);
  const brightness = calculateBrightness(menuColor);

  return {
    primaryOklch: primaryOklch ?? undefined,
    primaryForeground: brightness > 0.5 ? "oklch(0 0 0)" : "oklch(1 0 0)",
    backgroundTint: hexToRgba(menuColor, PATTERN_BACKGROUND_OPACITY),
    bgPatternVector: hexToRgba(menuColor, PATTERN_VECTOR_OPACITY),
    primaryLight: hexToRgba(menuColor, PRIMARY_LIGHT_OPACITY),
  };
}

export function getThemeCache(slug: string): CachedRestaurantTheme | null {
  if (!slug || typeof window === "undefined") return null;

  try {
    const raw = localStorage.getItem(getThemeCacheKey(slug));
    if (!raw) return null;

    const parsed = JSON.parse(raw) as CachedRestaurantTheme;
    if (parsed.version !== CACHE_VERSION || !parsed.menuColor) return null;

    if (!parsed.primaryOklch) {
      const enriched: CachedRestaurantTheme = {
        ...parsed,
        ...computeThemeCssValues(parsed.menuColor),
        version: CACHE_VERSION,
      };

      try {
        localStorage.setItem(getThemeCacheKey(slug), JSON.stringify(enriched));
      } catch {
        // Ignore quota errors during migration
      }

      return enriched;
    }

    return parsed;
  } catch {
    return null;
  }
}

export function getCachedMenuColor(slug?: string | null): string | null {
  if (slug) {
    const cached = getThemeCache(slug);
    if (cached?.menuColor) return cached.menuColor;
  }

  if (typeof window === "undefined") return null;

  try {
    return localStorage.getItem(LEGACY_COLOR_KEY);
  } catch {
    return null;
  }
}

export function getPersistedAboutData(slug: string): AboutResponse | undefined {
  if (!slug || typeof window === "undefined") return undefined;

  try {
    const raw = localStorage.getItem(getAboutCacheKey(slug));
    if (!raw) return undefined;
    return JSON.parse(raw) as AboutResponse;
  } catch {
    return undefined;
  }
}

export function setPersistedAboutData(slug: string, data: AboutResponse): void {
  if (!slug || typeof window === "undefined") return;

  try {
    localStorage.setItem(getAboutCacheKey(slug), JSON.stringify(data));
  } catch {
    // Ignore quota errors
  }
}

function readPersistedQueryData<T>(key: string): T | undefined {
  try {
    const raw = localStorage.getItem(key);
    if (!raw) return undefined;
    return JSON.parse(raw) as T;
  } catch {
    return undefined;
  }
}

function writePersistedQueryData<T>(key: string, data: T): void {
  try {
    localStorage.setItem(key, JSON.stringify(data));
  } catch {
    // Ignore quota errors
  }
}

export function getPersistedMenuData(slug: string): FoodsResponse | undefined {
  if (!slug || typeof window === "undefined") return undefined;
  return readPersistedQueryData<FoodsResponse>(getMenuCacheKey(slug));
}

export function setPersistedMenuData(slug: string, data: FoodsResponse): void {
  if (!slug || typeof window === "undefined") return;
  writePersistedQueryData(getMenuCacheKey(slug), data);
}

export function getPersistedCategoriesData(
  slug: string,
): CategoriesResponse | undefined {
  if (!slug || typeof window === "undefined") return undefined;
  return readPersistedQueryData<CategoriesResponse>(getCategoriesCacheKey(slug));
}

export function setPersistedCategoriesData(
  slug: string,
  data: CategoriesResponse,
): void {
  if (!slug || typeof window === "undefined") return;
  writePersistedQueryData(getCategoriesCacheKey(slug), data);
}

export function restorePersistedRestaurantQueries(
  client: QueryClient,
  slug: string,
): void {
  const about = getPersistedAboutData(slug);
  if (about) {
    client.setQueryData(["about", slug], about);
  }

  const menu = getPersistedMenuData(slug);
  if (menu) {
    client.setQueryData(["menu", slug], menu);
  }

  const categories = getPersistedCategoriesData(slug);
  if (categories) {
    client.setQueryData(["categories", slug], categories);
  }
}

export function setThemeCache(
  slug: string,
  theme: Omit<CachedRestaurantTheme, "version">,
): void {
  if (!slug || typeof window === "undefined") return;

  const existing = getThemeCache(slug);
  const css = computeThemeCssValues(theme.menuColor);
  const payload: CachedRestaurantTheme = {
    ...theme,
    ...css,
    patternDataUrl:
      theme.patternDataUrl !== undefined
        ? theme.patternDataUrl
        : (existing?.patternDataUrl ?? null),
    version: CACHE_VERSION,
  };

  try {
    localStorage.setItem(getThemeCacheKey(slug), JSON.stringify(payload));
    localStorage.setItem(LEGACY_COLOR_KEY, theme.menuColor);
  } catch {
    try {
      const { patternDataUrl: _pattern, ...withoutPattern } = payload;
      localStorage.setItem(
        getThemeCacheKey(slug),
        JSON.stringify({ ...withoutPattern, patternDataUrl: null }),
      );
      localStorage.setItem(LEGACY_COLOR_KEY, theme.menuColor);
    } catch {
      // Ignore quota errors
    }
  }
}

export function buildThemeCacheFromRestaurant(
  settings: RestaurantBackgroundSettings,
): Pick<
  CachedRestaurantTheme,
  | "menuColor"
  | "bgType"
  | "bgUrl"
  | "bgBlur"
  | "bgOpacity"
  | "bgOverlay"
  | "isPattern"
> {
  const bgType = resolveBgType(settings);

  return {
    menuColor: settings.menuColor || "#1E3A8A",
    bgType,
    bgUrl: settings.bgUrl,
    bgBlur: normalizeBgNumber(settings.bgBlur),
    bgOpacity: normalizeBgNumber(settings.bgOpacity),
    bgOverlay: settings.bgOverlay ?? null,
    isPattern: bgType === "pattern",
  };
}

export function themeBackgroundMatches(
  cached: CachedRestaurantTheme,
  settings: RestaurantBackgroundSettings,
): boolean {
  const next = buildThemeCacheFromRestaurant(settings);
  return (
    cached.menuColor === next.menuColor &&
    cached.bgType === next.bgType &&
    cached.bgUrl === next.bgUrl &&
    cached.bgBlur === next.bgBlur &&
    cached.bgOpacity === next.bgOpacity &&
    cached.bgOverlay === next.bgOverlay &&
    cached.isPattern === next.isPattern
  );
}

export function svgToDataUrl(svg: string): string {
  return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
}

function ensureBgElement(): HTMLElement {
  let bgElement = document.getElementById(THEME_BG_ELEMENT_ID);
  if (!bgElement) {
    bgElement = document.createElement("div");
    bgElement.id = THEME_BG_ELEMENT_ID;
    bgElement.setAttribute("aria-hidden", "true");
    bgElement.style.position = "fixed";
    bgElement.style.inset = "0";
    bgElement.style.pointerEvents = "none";
    bgElement.style.zIndex = "0";
    document.body.appendChild(bgElement);
  }
  return bgElement;
}

export function applyCachedThemeToDom(theme: CachedRestaurantTheme): void {
  if (typeof document === "undefined") return;

  const root = document.documentElement;

  if (theme.primaryOklch) {
    root.style.setProperty("--primary", theme.primaryOklch);
    root.style.setProperty(
      "--primary-foreground",
      theme.primaryForeground ?? "oklch(1 0 0)",
    );
  }

  if (isNightModeEnabled()) {
    clearRestaurantBackgroundOverrides();
    return;
  }

  const bgType = resolveBgType(theme);

  if (bgType === "color") {
    document.getElementById(THEME_BG_ELEMENT_ID)?.remove();
    const tint =
      theme.backgroundTint ??
      hexToRgba(theme.menuColor, PATTERN_BACKGROUND_OPACITY);
    const primaryLight =
      theme.primaryLight ??
      hexToRgba(theme.menuColor, PRIMARY_LIGHT_OPACITY);
    root.removeAttribute("data-pattern-bg");
    root.removeAttribute("data-image-bg");
    root.style.removeProperty("--bg-pattern-base");
    root.style.removeProperty("--bg-pattern-vector");
    root.style.setProperty("--background", tint);
    root.style.setProperty("--primary-light", primaryLight);
    return;
  }

  if (bgType === "pattern") {
    root.setAttribute("data-pattern-bg", "true");
    root.removeAttribute("data-image-bg");

    if (theme.backgroundTint) {
      root.style.setProperty("--background", theme.backgroundTint);
      root.style.setProperty("--bg-pattern-base", theme.backgroundTint);
    }
    if (theme.bgPatternVector) {
      root.style.setProperty("--bg-pattern-vector", theme.bgPatternVector);
    }
    if (theme.primaryLight) {
      root.style.setProperty("--primary-light", theme.primaryLight);
    }

    if (!theme.backgroundTint) return;

    const bgElement = ensureBgElement();
    bgElement.style.overflow = "";

    document.getElementById(THEME_BG_IMG_ID)?.remove();
    document.getElementById(THEME_BG_OVERLAY_ID)?.remove();

    bgElement.style.backgroundColor = theme.backgroundTint;
    if (theme.patternDataUrl) {
      bgElement.style.backgroundImage = `url("${theme.patternDataUrl}")`;
      bgElement.style.backgroundRepeat = "repeat";
      bgElement.style.backgroundSize = "auto";
    } else {
      bgElement.style.removeProperty("background-image");
      bgElement.style.removeProperty("background-repeat");
      bgElement.style.removeProperty("background-size");
    }
    return;
  }

  if (bgType === "custom" && theme.bgUrl) {
    root.setAttribute("data-image-bg", "true");
    root.removeAttribute("data-pattern-bg");

    const bgElement = ensureBgElement();
    bgElement.style.backgroundColor = "";
    bgElement.style.backgroundImage = "";
    bgElement.style.overflow = "hidden";

    let imgLayer = document.getElementById(THEME_BG_IMG_ID);
    if (!imgLayer) {
      imgLayer = document.createElement("div");
      imgLayer.id = THEME_BG_IMG_ID;
      imgLayer.style.position = "absolute";
      imgLayer.style.inset = "-40px";
      imgLayer.style.backgroundSize = "cover";
      imgLayer.style.backgroundPosition = "center";
      imgLayer.style.backgroundRepeat = "no-repeat";
      bgElement.appendChild(imgLayer);
    }

    imgLayer.style.backgroundImage = `url("${theme.bgUrl}")`;
    imgLayer.style.filter = theme.bgBlur ? `blur(${theme.bgBlur}px)` : "";
    imgLayer.style.opacity =
      theme.bgOpacity != null ? String(theme.bgOpacity / 100) : "1";

    let overlayLayer = document.getElementById(THEME_BG_OVERLAY_ID);
    if (!overlayLayer) {
      overlayLayer = document.createElement("div");
      overlayLayer.id = THEME_BG_OVERLAY_ID;
      overlayLayer.style.position = "absolute";
      overlayLayer.style.inset = "0";
      bgElement.appendChild(overlayLayer);
    }

    const overlayOpacity =
      theme.bgOverlay != null ? Number(theme.bgOverlay) / 100 : 0;
    overlayLayer.style.backgroundColor =
      overlayOpacity > 0 ? `rgba(0,0,0,${overlayOpacity})` : "";
  }
}

export function removeCachedThemeBackground(): void {
  document.getElementById(THEME_BG_ELEMENT_ID)?.remove();
}
