"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { ImagePlus, Video, X } from "lucide-react";
import { cn } from "@/lib/utils";

export function MindavioLogo({
  size = 32,
  className,
}: {
  color?: string;
  size?: number;
  className?: string;
}) {
  return (
    // eslint-disable-next-line @next/next/no-img-element
    <img
      src="/mindavio-logo.png"
      alt=""
      width={size}
      height={size}
      className={className}
      style={{
        width: size,
        height: size,
        objectFit: "contain",
        filter: "invert(1) brightness(2)",
        mixBlendMode: "screen",
      }}
      draggable={false}
    />
  );
}

/* ── Compact icon for small uses (sidebar, header badges) ── */
export function MindavioLogoCompact({
  size = 20,
}: {
  color?: string;
  size?: number;
}) {
  return (
    // eslint-disable-next-line @next/next/no-img-element
    <img
      src="/mindavio-logo.png"
      alt=""
      width={size}
      height={size}
      style={{
        width: size,
        height: size,
        objectFit: "contain",
        filter: "invert(1) brightness(2)",
        mixBlendMode: "screen",
      }}
      draggable={false}
    />
  );
}

/* ─── Background presets ─── */

export interface BgPreset {
  id: string;
  label: string;
  bg: string;
  textColor: string;
  accentColor: string;
  subtleColor: string;
  showLogo?: boolean;
}

export const BG_PRESETS: BgPreset[] = [
  {
    id: "mb-dark",
    label: "Mindavio Dark",
    bg: "linear-gradient(135deg, #0f0f1a 0%, #1a1033 40%, #0d1117 100%)",
    textColor: "#ffffff",
    accentColor: "#818cf8",
    subtleColor: "rgba(255,255,255,0.5)",
    showLogo: true,
  },
  {
    id: "mb-indigo",
    label: "Mindavio Indigo",
    bg: "linear-gradient(135deg, #1e1b4b 0%, #312e81 40%, #1e1b4b 100%)",
    textColor: "#ffffff",
    accentColor: "#a5b4fc",
    subtleColor: "rgba(255,255,255,0.5)",
    showLogo: true,
  },
  {
    id: "mb-neon",
    label: "Mindavio Neon",
    bg: "linear-gradient(135deg, #0a0a0a 0%, #0f172a 40%, #020617 100%)",
    textColor: "#ffffff",
    accentColor: "#22d3ee",
    subtleColor: "rgba(255,255,255,0.45)",
    showLogo: true,
  },
  {
    id: "clean-light",
    label: "Clean Light",
    bg: "linear-gradient(135deg, #ffffff 0%, #f8fafc 50%, #f1f5f9 100%)",
    textColor: "#0f172a",
    accentColor: "#6366f1",
    subtleColor: "rgba(15,23,42,0.45)",
  },
  {
    id: "warm-light",
    label: "Warm Light",
    bg: "linear-gradient(135deg, #fffbeb 0%, #fef3c7 50%, #fde68a 100%)",
    textColor: "#451a03",
    accentColor: "#d97706",
    subtleColor: "rgba(69,26,3,0.4)",
  },
  {
    id: "soft-rose",
    label: "Soft Rose",
    bg: "linear-gradient(135deg, #fff1f2 0%, #ffe4e6 50%, #fecdd3 100%)",
    textColor: "#4c0519",
    accentColor: "#e11d48",
    subtleColor: "rgba(76,5,25,0.4)",
  },
  {
    id: "midnight",
    label: "Midnight",
    bg: "linear-gradient(135deg, #0c0c0c 0%, #1a1a2e 50%, #16213e 100%)",
    textColor: "#ffffff",
    accentColor: "#60a5fa",
    subtleColor: "rgba(255,255,255,0.45)",
  },
  {
    id: "aurora",
    label: "Aurora",
    bg: "linear-gradient(135deg, #0f172a 0%, #1e1b4b 40%, #064e3b 100%)",
    textColor: "#ffffff",
    accentColor: "#34d399",
    subtleColor: "rgba(255,255,255,0.5)",
  },
  {
    id: "sunset",
    label: "Sunset",
    bg: "linear-gradient(135deg, #1a0a2e 0%, #2d1b4e 30%, #4a1942 60%, #1a0a2e 100%)",
    textColor: "#ffffff",
    accentColor: "#f472b6",
    subtleColor: "rgba(255,255,255,0.45)",
  },
  {
    id: "emerald",
    label: "Emerald",
    bg: "linear-gradient(135deg, #022c22 0%, #064e3b 40%, #065f46 100%)",
    textColor: "#ffffff",
    accentColor: "#6ee7b7",
    subtleColor: "rgba(255,255,255,0.5)",
  },
  {
    id: "obsidian",
    label: "Obsidian",
    bg: "linear-gradient(135deg, #0a0a0a 0%, #171717 50%, #0a0a0a 100%)",
    textColor: "#ffffff",
    accentColor: "#a1a1aa",
    subtleColor: "rgba(255,255,255,0.4)",
  },
  {
    id: "ocean",
    label: "Ocean",
    bg: "linear-gradient(135deg, #0c4a6e 0%, #075985 40%, #0369a1 100%)",
    textColor: "#ffffff",
    accentColor: "#7dd3fc",
    subtleColor: "rgba(255,255,255,0.5)",
  },
];

const CUSTOM_BG_STORAGE_KEY = "mindavio-custom-bg";
const CUSTOM_BG_DB_NAME = "mindavio-custom-bg-db";
const CUSTOM_BG_STORE_NAME = "backgrounds";
const CUSTOM_BG_FILE_ID = "active-background";

type CustomBackground =
  | {
      dataUrl: string;
      fileName?: string;
      type: "image";
    }
  | {
      dataUrl: string;
      fileName?: string;
      posterUrl: string | null;
      storedInIndexedDb?: boolean;
      type: "video";
    };

function openCustomBgDb() {
  return new Promise<IDBDatabase>((resolve, reject) => {
    if (typeof indexedDB === "undefined") {
      reject(new Error("Background storage wird von diesem Browser nicht unterstützt."));
      return;
    }

    const request = indexedDB.open(CUSTOM_BG_DB_NAME, 1);
    request.onupgradeneeded = () => {
      request.result.createObjectStore(CUSTOM_BG_STORE_NAME);
    };
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error || new Error("Background storage konnte nicht geöffnet werden."));
  });
}

async function putCustomBgFile(file: File) {
  const db = await openCustomBgDb();
  await new Promise<void>((resolve, reject) => {
    const tx = db.transaction(CUSTOM_BG_STORE_NAME, "readwrite");
    tx.objectStore(CUSTOM_BG_STORE_NAME).put(file, CUSTOM_BG_FILE_ID);
    tx.oncomplete = () => resolve();
    tx.onerror = () => reject(tx.error || new Error("Video-Hintergrund konnte nicht gespeichert werden."));
  });
  db.close();
}

async function getCustomBgFile() {
  const db = await openCustomBgDb();
  const blob = await new Promise<Blob | null>((resolve, reject) => {
    const tx = db.transaction(CUSTOM_BG_STORE_NAME, "readonly");
    const request = tx.objectStore(CUSTOM_BG_STORE_NAME).get(CUSTOM_BG_FILE_ID);
    request.onsuccess = () => resolve((request.result as Blob | undefined) || null);
    request.onerror = () => reject(request.error || new Error("Video-Hintergrund konnte nicht geladen werden."));
  });
  db.close();

  return blob;
}

async function deleteCustomBgFile() {
  const db = await openCustomBgDb();
  await new Promise<void>((resolve, reject) => {
    const tx = db.transaction(CUSTOM_BG_STORE_NAME, "readwrite");
    tx.objectStore(CUSTOM_BG_STORE_NAME).delete(CUSTOM_BG_FILE_ID);
    tx.oncomplete = () => resolve();
    tx.onerror = () => reject(tx.error || new Error("Video-Hintergrund konnte nicht gelöscht werden."));
  });
  db.close();
}

function loadCustomBg(): CustomBackground | null {
  if (typeof window === "undefined") return null;
  try {
    const raw = localStorage.getItem(CUSTOM_BG_STORAGE_KEY);
    if (!raw) return null;

    if (raw.startsWith("data:")) {
      return { dataUrl: raw, type: "image" };
    }

    const parsed = JSON.parse(raw) as Partial<CustomBackground>;
    if (parsed?.type === "image" && typeof parsed.dataUrl === "string") {
      return {
        dataUrl: parsed.dataUrl,
        fileName: typeof parsed.fileName === "string" ? parsed.fileName : undefined,
        type: "image",
      };
    }
    if (parsed?.type === "video") {
      const dataUrl = typeof parsed.dataUrl === "string" && !parsed.dataUrl.startsWith("blob:")
        ? parsed.dataUrl
        : "";

      return {
        dataUrl,
        fileName: typeof parsed.fileName === "string" ? parsed.fileName : undefined,
        posterUrl: typeof parsed.posterUrl === "string" ? parsed.posterUrl : null,
        storedInIndexedDb: true,
        type: "video",
      };
    }

    return null;
  } catch {
    return null;
  }
}

function saveCustomBg(background: CustomBackground | null) {
  if (typeof window === "undefined") return;
  try {
    if (background?.type === "video") {
      localStorage.setItem(CUSTOM_BG_STORAGE_KEY, JSON.stringify({
        fileName: background.fileName,
        posterUrl: background.posterUrl,
        storedInIndexedDb: true,
        type: "video",
      }));
      return;
    }

    if (background) {
      localStorage.setItem(CUSTOM_BG_STORAGE_KEY, JSON.stringify(background));
    }
    else localStorage.removeItem(CUSTOM_BG_STORAGE_KEY);
  } catch {
    // Large video data URLs may exceed storage limits. The in-memory preview still works.
  }
}

export function useBackgroundPicker(defaultPresetId = "mb-dark") {
  const [presetId, setPresetId] = useState(() => loadCustomBg() ? "__custom" : defaultPresetId);
  const [customBackground, setCustomBackground] = useState<CustomBackground | null>(() => loadCustomBg());

  useEffect(() => {
    const objectUrl =
      customBackground?.type === "video" && customBackground.dataUrl.startsWith("blob:")
        ? customBackground.dataUrl
        : null;

    return () => {
      if (objectUrl) URL.revokeObjectURL(objectUrl);
    };
  }, [customBackground]);

  useEffect(() => {
    if (customBackground?.type !== "video" || customBackground.dataUrl) return;

    let objectUrl: string | null = null;
    let ownershipTransferred = false;
    let cancelled = false;

    void getCustomBgFile()
      .then((blob) => {
        if (!blob) throw new Error("Kein gespeicherter Video-Hintergrund gefunden.");
        objectUrl = URL.createObjectURL(blob);

        if (cancelled) {
          URL.revokeObjectURL(objectUrl);
          return;
        }

        setCustomBackground((current) => {
          if (current?.type !== "video") return current;
          return {
            ...current,
            dataUrl: objectUrl || "",
          };
        });
        ownershipTransferred = true;
        setPresetId("__custom");
      })
      .catch(() => {
        saveCustomBg(null);
        void deleteCustomBgFile().catch(() => undefined);
        setCustomBackground(null);
        setPresetId(defaultPresetId);
      });

    return () => {
      cancelled = true;
      if (objectUrl && !ownershipTransferred) URL.revokeObjectURL(objectUrl);
    };
  }, [customBackground, defaultPresetId]);

  const preset = BG_PRESETS.find((p) => p.id === presetId) || BG_PRESETS[0];
  const isCustom = presetId === "__custom" && !!customBackground;
  const customImage =
    customBackground?.type === "image"
      ? customBackground.dataUrl
      : customBackground?.posterUrl ?? null;
  const customVideo = customBackground?.type === "video" ? customBackground.dataUrl : null;
  const isCustomVideo = isCustom && customBackground?.type === "video";

  const bgStyle: React.CSSProperties = isCustom
    ? customImage
      ? {
          backgroundImage: `url(${customImage})`,
          backgroundSize: "cover",
          backgroundPosition: "center",
        }
      : { background: "#050508" }
    : { background: preset.bg };

  const theme = isCustom
    ? { textColor: "#ffffff", accentColor: "#818cf8", subtleColor: "rgba(255,255,255,0.55)", showLogo: false }
    : { textColor: preset.textColor, accentColor: preset.accentColor, subtleColor: preset.subtleColor, showLogo: preset.showLogo ?? false };

  const handleUpload = useCallback((file: File) => {
    if (file.type.startsWith("video/")) {
      const objectUrl = URL.createObjectURL(file);
      void createVideoPoster(objectUrl).then(async (posterUrl) => {
        const nextBackground: CustomBackground = {
          dataUrl: objectUrl,
          fileName: file.name,
          posterUrl,
          storedInIndexedDb: true,
          type: "video",
        };

        await putCustomBgFile(file).catch(() => undefined);
        setCustomBackground(nextBackground);
        saveCustomBg(nextBackground);
        setPresetId("__custom");
      });
      return;
    }

    const reader = new FileReader();
    reader.onload = (e) => {
      const result = e.target?.result as string;
      const nextBackground: CustomBackground = {
        dataUrl: result,
        fileName: file.name,
        type: "image",
      };

      void deleteCustomBgFile().catch(() => undefined);
      setCustomBackground(nextBackground);
      saveCustomBg(nextBackground);
      setPresetId("__custom");
    };
    reader.readAsDataURL(file);
  }, []);

  const removeCustom = useCallback(() => {
    setCustomBackground(null);
    saveCustomBg(null);
    void deleteCustomBgFile().catch(() => undefined);
    setPresetId("mb-dark");
  }, []);

  return {
    presetId,
    setPresetId,
    customImage,
    customVideo,
    isCustom,
    isCustomVideo,
    bgStyle,
    theme,
    handleUpload,
    removeCustom,
  };
}

function createVideoPoster(dataUrl: string): Promise<string | null> {
  return new Promise((resolve) => {
    const video = document.createElement("video");
    video.muted = true;
    video.playsInline = true;
    video.preload = "auto";
    video.src = dataUrl;

    const cleanup = () => {
      video.removeAttribute("src");
      video.load();
    };

    const capture = () => {
      try {
        const canvas = document.createElement("canvas");
        canvas.width = video.videoWidth || 1280;
        canvas.height = video.videoHeight || 720;
        const ctx = canvas.getContext("2d");
        if (!ctx) {
          cleanup();
          resolve(null);
          return;
        }
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
        const poster = canvas.toDataURL("image/jpeg", 0.82);
        cleanup();
        resolve(poster);
      } catch {
        cleanup();
        resolve(null);
      }
    };

    const handleReady = () => {
      if (video.duration && Number.isFinite(video.duration)) {
        video.currentTime = Math.min(0.12, Math.max(video.duration - 0.05, 0));
      } else {
        capture();
      }
    };

    video.addEventListener("loadedmetadata", handleReady, { once: true });
    video.addEventListener("loadeddata", handleReady, { once: true });
    video.addEventListener("seeked", capture, { once: true });
    video.addEventListener("error", () => {
      cleanup();
      resolve(null);
    }, { once: true });
  });
}

export function BackgroundVideoLayer({
  muted = true,
  src,
}: {
  muted?: boolean;
  src: string | null;
}) {
  const videoRef = useRef<HTMLVideoElement>(null);

  // React's `muted` prop has a known bug where it doesn't update the DOM attribute
  // after mount. We control it imperatively via a ref instead.
  useEffect(() => {
    const el = videoRef.current;
    if (!el) return;
    el.muted = muted;
  }, [muted]);

  if (!src) return null;

  return (
    <video
      ref={videoRef}
      aria-hidden="true"
      autoPlay
      className="pointer-events-none absolute inset-0 h-full w-full object-cover"
      loop
      muted           // initial attribute — overridden imperatively above
      playsInline
      src={src}
    />
  );
}

/* ─── Background picker UI ─── */

interface BackgroundPickerProps {
  presetId: string;
  customImage: string | null;
  customVideo?: string | null;
  onSelectPreset: (id: string) => void;
  onUpload: (file: File) => void;
  onRemoveCustom: () => void;
}

export function BackgroundPicker({
  presetId,
  customImage,
  customVideo = null,
  onSelectPreset,
  onUpload,
  onRemoveCustom,
}: BackgroundPickerProps) {
  const fileRef = useRef<HTMLInputElement>(null);

  return (
    <div>
      <p className="text-xs text-muted-foreground mb-2">Hintergrund</p>
      <div className="flex flex-wrap items-center gap-2">
        {BG_PRESETS.map((bg) => (
          <button
            key={bg.id}
            onClick={() => onSelectPreset(bg.id)}
            title={bg.label}
            className={cn(
              "relative h-9 w-9 rounded-lg border-2 transition-all overflow-hidden",
              presetId === bg.id
                ? "border-foreground scale-110 shadow-md"
                : "border-transparent hover:border-border hover:scale-105"
            )}
            style={{ background: bg.bg }}
          >
            {bg.showLogo && (
              <div className="absolute inset-0 flex items-center justify-center opacity-30">
                <MindavioLogoCompact color={bg.accentColor} size={18} />
              </div>
            )}
          </button>
        ))}

        {customImage || customVideo ? (
          <div className="relative">
            <button
              onClick={() => onSelectPreset("__custom")}
          title={customVideo ? "Eigenes Video" : "Eigenes Bild"}
              className={cn(
                "h-9 w-9 rounded-lg border-2 transition-all overflow-hidden",
                presetId === "__custom"
                  ? "border-foreground scale-110 shadow-md"
                  : "border-transparent hover:border-border hover:scale-105"
              )}
              style={{ backgroundImage: customImage ? `url(${customImage})` : undefined, backgroundSize: "cover", backgroundPosition: "center" }}
            >
              {customVideo && (
                <div className="absolute inset-0 flex items-center justify-center bg-black/35">
                  <Video className="h-4 w-4 text-white" />
                </div>
              )}
            </button>
            <button
              onClick={onRemoveCustom}
              className="absolute -top-1.5 -right-1.5 flex h-4 w-4 items-center justify-center rounded-full bg-destructive text-white shadow-sm"
            >
              <X className="h-2.5 w-2.5" />
            </button>
          </div>
        ) : null}

        <div className="flex flex-col items-center gap-0.5">
          <button
            onClick={() => fileRef.current?.click()}
            title="Eigenes Bild oder Video hochladen"
            className="flex h-9 w-9 items-center justify-center rounded-lg border-2 border-dashed border-border/60 text-muted-foreground transition-all hover:border-border hover:text-foreground hover:scale-105"
          >
            <div className="relative">
              <ImagePlus className="h-4 w-4" />
              <Video className="absolute -bottom-1.5 -right-1.5 h-2.5 w-2.5 rounded-sm bg-background text-muted-foreground" />
            </div>
          </button>
          <span className="text-[9px] text-muted-foreground/60 leading-none">Bild/Vid</span>
        </div>
        <input
          ref={fileRef}
          type="file"
          accept="image/*,video/*"
          className="hidden"
          onChange={(e) => {
            const file = e.target.files?.[0];
            if (file) onUpload(file);
            e.target.value = "";
          }}
        />
      </div>
    </div>
  );
}
