"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { Download, Eye, FileText, History, ImageIcon, Send, Sparkles, Trash2, Video } from "lucide-react";
import { ShareToChatModal, type ChatSharePayload } from "@/components/chat/share-to-chat-modal";
import { Modal } from "@/components/ui/modal";
import { cn } from "@/lib/utils";

export type ReviewArtifactType = "finance" | "focus" | "journal";

export interface ReviewGalleryArtifact {
  createdAt: number;
  fileKind?: "image" | "pdf" | "video" | "file";
  fileName: string;
  fileSize?: number;
  fileType?: string;
  id: string;
  message: string;
  title: string;
  type: ReviewArtifactType;
}

interface ReviewShareStudioProps {
  artifactType: ReviewArtifactType;
  buildPayload: () => Promise<ChatSharePayload>;
  children: React.ReactNode;
  className?: string;
  controls?: React.ReactNode;
  defaultMessage: string;
  description: string;
  downloadLabel?: string;
  icon?: React.ReactNode;
  onDownloaded?: () => void;
  shareDescription: string;
  shareTitle: string;
  tone?: "amber" | "emerald" | "violet";
  title: string;
}

const GALLERY_STORAGE_KEY = "mindavio-review-gallery";
const GALLERY_DB_NAME = "mindavio-review-gallery-db";
const GALLERY_STORE_NAME = "artifacts";

const TONE = {
  amber: {
    accent: "text-amber-300",
    button: "bg-amber-500/[0.12] text-amber-100 hover:bg-amber-500/[0.18] border-amber-500/20",
    icon: "from-amber-500 to-orange-600",
    shadow: "hover:border-amber-500/20 hover:shadow-[0_0_30px_-10px_rgba(245,158,11,0.2)]",
  },
  emerald: {
    accent: "text-emerald-300",
    button: "bg-emerald-500/[0.12] text-emerald-100 hover:bg-emerald-500/[0.18] border-emerald-500/20",
    icon: "from-emerald-500 to-teal-600",
    shadow: "hover:border-emerald-500/20 hover:shadow-[0_0_30px_-10px_rgba(16,185,129,0.18)]",
  },
  violet: {
    accent: "text-violet-300",
    button: "bg-violet-500/[0.12] text-violet-100 hover:bg-violet-500/[0.18] border-violet-500/20",
    icon: "from-violet-500 to-indigo-600",
    shadow: "hover:border-violet-500/20 hover:shadow-[0_0_30px_-10px_rgba(139,92,246,0.2)]",
  },
};

export function dataUrlToFile(dataUrl: string, fileName: string) {
  const [meta, base64] = dataUrl.split(",");
  const mimeType = meta.match(/data:(.*?);base64/)?.[1] || "image/png";
  const binary = atob(base64);
  const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
  return new File([bytes], fileName, { type: mimeType });
}

function loadGallery(): ReviewGalleryArtifact[] {
  if (typeof window === "undefined") return [];
  try {
    const raw = localStorage.getItem(GALLERY_STORAGE_KEY);
    if (!raw) return [];
    const parsed = JSON.parse(raw) as ReviewGalleryArtifact[];
    return Array.isArray(parsed) ? parsed : [];
  } catch {
    return [];
  }
}

function saveGallery(artifacts: ReviewGalleryArtifact[]) {
  if (typeof window === "undefined") return;
  try {
    localStorage.setItem(GALLERY_STORAGE_KEY, JSON.stringify(artifacts.slice(0, 24)));
  } catch {
    // Gallery metadata is nice-to-have only.
  }
}

function formatFileSize(bytes = 0) {
  if (!bytes) return "—";
  if (bytes < 1024 * 1024) return `${Math.max(1, Math.round(bytes / 1024))} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

function getFileKind(file: File): ReviewGalleryArtifact["fileKind"] {
  if (file.type.startsWith("video/")) return "video";
  if (file.type.startsWith("image/")) return "image";
  if (file.type === "application/pdf") return "pdf";
  return "file";
}

function getKindIcon(kind: ReviewGalleryArtifact["fileKind"]) {
  if (kind === "video") return <Video className="h-3.5 w-3.5 text-emerald-300" />;
  if (kind === "image") return <ImageIcon className="h-3.5 w-3.5 text-violet-300" />;
  if (kind === "pdf") return <FileText className="h-3.5 w-3.5 text-amber-300" />;
  return <Sparkles className="h-3.5 w-3.5 text-white/45" />;
}

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

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

async function putGalleryFile(id: string, file: File) {
  const db = await openGalleryDb();
  await new Promise<void>((resolve, reject) => {
    const tx = db.transaction(GALLERY_STORE_NAME, "readwrite");
    tx.objectStore(GALLERY_STORE_NAME).put(file, id);
    tx.oncomplete = () => resolve();
    tx.onerror = () => reject(tx.error || new Error("Review konnte nicht gespeichert werden."));
  });
  db.close();
}

async function getGalleryFile(artifact: ReviewGalleryArtifact) {
  const db = await openGalleryDb();
  const blob = await new Promise<Blob | null>((resolve, reject) => {
    const tx = db.transaction(GALLERY_STORE_NAME, "readonly");
    const request = tx.objectStore(GALLERY_STORE_NAME).get(artifact.id);
    request.onsuccess = () => resolve((request.result as Blob | undefined) || null);
    request.onerror = () => reject(request.error || new Error("Review konnte nicht geladen werden."));
  });
  db.close();

  if (!blob) throw new Error("Diese Review-Datei ist nicht mehr in der lokalen Gallery gespeichert.");
  return new File([blob], artifact.fileName, { type: artifact.fileType || blob.type });
}

async function deleteGalleryFile(id: string) {
  const db = await openGalleryDb();
  await new Promise<void>((resolve, reject) => {
    const tx = db.transaction(GALLERY_STORE_NAME, "readwrite");
    tx.objectStore(GALLERY_STORE_NAME).delete(id);
    tx.oncomplete = () => resolve();
    tx.onerror = () => reject(tx.error || new Error("Review konnte nicht gelöscht werden."));
  });
  db.close();
}

function downloadFile(file: File) {
  const objectUrl = URL.createObjectURL(file);
  const link = document.createElement("a");
  link.download = file.name;
  link.href = objectUrl;
  link.click();
  window.setTimeout(() => URL.revokeObjectURL(objectUrl), 1000);
}

export function ReviewShareStudio({
  artifactType,
  buildPayload,
  children,
  className,
  controls,
  defaultMessage,
  description,
  downloadLabel = "Als Datei speichern",
  icon,
  onDownloaded,
  shareDescription,
  shareTitle,
  title,
  tone = "violet",
}: ReviewShareStudioProps) {
  const [exporting, setExporting] = useState(false);
  const [showShareToChat, setShowShareToChat] = useState(false);
  const [galleryShareArtifact, setGalleryShareArtifact] = useState<ReviewGalleryArtifact | null>(null);
  const [galleryPreviewArtifact, setGalleryPreviewArtifact] = useState<ReviewGalleryArtifact | null>(null);
  const [galleryPreviewError, setGalleryPreviewError] = useState("");
  const [galleryPreviewFile, setGalleryPreviewFile] = useState<File | null>(null);
  const [galleryPreviewLoading, setGalleryPreviewLoading] = useState(false);
  const [galleryPreviewUrl, setGalleryPreviewUrl] = useState<string | null>(null);
  const [galleryActionId, setGalleryActionId] = useState<string | null>(null);
  const [gallery, setGallery] = useState<ReviewGalleryArtifact[]>([]);
  const toneCfg = TONE[tone];

  useEffect(() => {
    setGallery(loadGallery());
  }, []);

  useEffect(() => {
    if (!galleryPreviewArtifact) {
      setGalleryPreviewError("");
      setGalleryPreviewFile(null);
      setGalleryPreviewLoading(false);
      setGalleryPreviewUrl(null);
      return;
    }

    let objectUrl: string | null = null;
    let cancelled = false;
    setGalleryPreviewError("");
    setGalleryPreviewFile(null);
    setGalleryPreviewLoading(true);
    setGalleryPreviewUrl(null);

    void getGalleryFile(galleryPreviewArtifact)
      .then((file) => {
        if (cancelled) return;
        objectUrl = URL.createObjectURL(file);
        setGalleryPreviewFile(file);
        setGalleryPreviewUrl(objectUrl);
      })
      .catch((error) => {
        if (!cancelled) {
          setGalleryPreviewError(error instanceof Error ? error.message : "Preview konnte nicht geladen werden.");
        }
      })
      .finally(() => {
        if (!cancelled) setGalleryPreviewLoading(false);
      });

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

  const scopedGallery = useMemo(
    () => gallery.filter((artifact) => artifact.type === artifactType).slice(0, 3),
    [artifactType, gallery],
  );

  const rememberArtifact = useCallback(
    async (payload: ChatSharePayload) => {
      const file = payload.files[0];
      if (!file) return;

      const fileName = file.name || `${artifactType}-review`;
      const nextArtifact: ReviewGalleryArtifact = {
        createdAt: Date.now(),
        fileKind: getFileKind(file),
        fileName,
        fileSize: file.size,
        fileType: file.type,
        id: `${artifactType}-${Date.now()}`,
        message: payload.message || defaultMessage,
        title,
        type: artifactType,
      };

      try {
        await putGalleryFile(nextArtifact.id, file);
      } catch {
        return;
      }

      setGallery((current) => {
        const next = [nextArtifact, ...current].slice(0, 24);
        saveGallery(next);
        return next;
      });
    },
    [artifactType, defaultMessage, title],
  );

  const buildAndRememberPayload = useCallback(async () => {
    const payload = await buildPayload();
    await rememberArtifact(payload);
    return payload;
  }, [buildPayload, rememberArtifact]);

  const handleGalleryDownload = useCallback(async (artifact: ReviewGalleryArtifact) => {
    setGalleryActionId(artifact.id);
    try {
      downloadFile(await getGalleryFile(artifact));
    } finally {
      setGalleryActionId(null);
    }
  }, []);

  const handleGalleryDelete = useCallback(async (artifact: ReviewGalleryArtifact) => {
    if (!window.confirm(`Review "${artifact.fileName}" aus der lokalen Gallery löschen?`)) return;

    setGalleryActionId(artifact.id);
    try {
      await deleteGalleryFile(artifact.id).catch(() => undefined);
      setGallery((current) => {
        const next = current.filter((item) => item.id !== artifact.id);
        saveGallery(next);
        return next;
      });
      if (galleryShareArtifact?.id === artifact.id) setGalleryShareArtifact(null);
      if (galleryPreviewArtifact?.id === artifact.id) setGalleryPreviewArtifact(null);
    } finally {
      setGalleryActionId(null);
    }
  }, [galleryPreviewArtifact?.id, galleryShareArtifact?.id]);

  const buildGalleryPayload = useCallback(async (): Promise<ChatSharePayload> => {
    if (!galleryShareArtifact) throw new Error("Wähle zuerst ein Review aus der Gallery.");
    return {
      files: [await getGalleryFile(galleryShareArtifact)],
      message: galleryShareArtifact.message || defaultMessage,
    };
  }, [defaultMessage, galleryShareArtifact]);

  const handleDownload = useCallback(async () => {
    setExporting(true);
    try {
      const payload = await buildAndRememberPayload();
      const file = payload.files[0];
      if (!file) return;
      downloadFile(file);
      onDownloaded?.();
    } finally {
      setExporting(false);
    }
  }, [buildAndRememberPayload, onDownloaded]);

  return (
    <div className={cn("rounded-[28px] border border-white/[0.08] bg-[#0f0d17]/84 p-5 shadow-[0_18px_60px_rgba(0,0,0,0.30)] transition-all", toneCfg.shadow, className)}>
      <div className="mb-5 flex flex-wrap items-start justify-between gap-4">
        <div className="flex items-center gap-3">
          <div className={cn("flex h-9 w-9 items-center justify-center rounded-xl bg-gradient-to-br", toneCfg.icon)}>
            {icon || <Sparkles className="h-4 w-4 text-white" />}
          </div>
          <div>
            <h2 className="text-sm font-semibold text-white">{title}</h2>
            <p className="text-xs text-white/35">{description}</p>
          </div>
        </div>

        <div className="flex flex-wrap gap-2">
          <button
            onClick={() => void handleDownload()}
            disabled={exporting}
            className="flex items-center gap-2 rounded-xl bg-white px-4 py-2 text-xs font-semibold text-black transition-all hover:opacity-90 disabled:opacity-50"
          >
            <Download className="h-3.5 w-3.5" />
            {exporting ? "Exportiert..." : downloadLabel}
          </button>
          <button
            onClick={() => setShowShareToChat(true)}
            className={cn("flex items-center gap-2 rounded-xl border px-4 py-2 text-xs font-semibold transition-all", toneCfg.button)}
          >
            <Send className="h-3.5 w-3.5" />
            An Chat senden
          </button>
        </div>
      </div>

      {controls && <div className="mb-5">{controls}</div>}

      {scopedGallery.length > 0 && (
        <div className="mb-5 rounded-2xl border border-white/[0.06] bg-white/[0.025] p-4">
          <div className="mb-3 flex items-center justify-between gap-3">
            <div className="flex items-center gap-2">
              <History className={cn("h-3.5 w-3.5", toneCfg.accent)} />
              <p className="text-[11px] font-bold uppercase tracking-[0.16em] text-white/30">
                Review Gallery
              </p>
            </div>
            <span className="text-[10px] text-white/22">lokal gespeichert</span>
          </div>
          <div className="grid gap-2 md:grid-cols-3">
            {scopedGallery.map((artifact) => (
              <div key={artifact.id} className="rounded-xl border border-white/[0.05] bg-white/[0.02] p-3">
                <div className="flex items-start justify-between gap-3">
                  <div className="flex min-w-0 items-center gap-2">
                    <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-white/[0.045]">
                      {getKindIcon(artifact.fileKind)}
                    </div>
                    <div className="min-w-0">
                      <p className="truncate text-[12px] font-semibold text-white/75">{artifact.fileName}</p>
                      <p className="mt-0.5 text-[10px] text-white/25">
                        {new Date(artifact.createdAt).toLocaleString("de-DE", {
                          day: "2-digit",
                          hour: "2-digit",
                          minute: "2-digit",
                          month: "2-digit",
                        })}
                        {" · "}
                        {formatFileSize(artifact.fileSize)}
                      </p>
                    </div>
                  </div>
                </div>
                <div className="mt-3 grid grid-cols-[1fr_1fr_1fr_auto] gap-2">
                  <button
                    onClick={() => setGalleryPreviewArtifact(artifact)}
                    className="flex items-center justify-center gap-1 rounded-lg border border-white/[0.07] bg-white/[0.035] px-2 py-1.5 text-[10px] font-semibold text-white/52 transition hover:bg-white/[0.06] hover:text-white/75"
                  >
                    <Eye className="h-3 w-3" />
                    Preview
                  </button>
                  <button
                    onClick={() => void handleGalleryDownload(artifact)}
                    className="rounded-lg border border-white/[0.07] bg-white/[0.035] px-2 py-1.5 text-[10px] font-semibold text-white/52 transition hover:bg-white/[0.06] hover:text-white/75"
                  >
                    {galleryActionId === artifact.id ? "Lädt..." : "Download"}
                  </button>
                  <button
                    onClick={() => setGalleryShareArtifact(artifact)}
                    className={cn("rounded-lg border px-2 py-1.5 text-[10px] font-semibold transition", toneCfg.button)}
                  >
                    Chat
                  </button>
                  <button
                    onClick={() => void handleGalleryDelete(artifact)}
                    className="flex h-7 w-7 items-center justify-center rounded-lg border border-red-500/10 bg-red-500/[0.04] text-red-200/45 transition hover:bg-red-500/[0.10] hover:text-red-200"
                    title="Review löschen"
                  >
                    <Trash2 className="h-3 w-3" />
                  </button>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}

      {children}

      {showShareToChat && (
        <ShareToChatModal
          open={showShareToChat}
          onClose={() => setShowShareToChat(false)}
          title={shareTitle}
          description={shareDescription}
          defaultMessage={defaultMessage}
          buildPayload={buildAndRememberPayload}
        />
      )}

      {galleryShareArtifact && (
        <ShareToChatModal
          open={Boolean(galleryShareArtifact)}
          onClose={() => setGalleryShareArtifact(null)}
          title="Review aus Gallery senden"
          description="Sende ein bereits exportiertes Review erneut als Chat-Anhang."
          defaultMessage={galleryShareArtifact.message}
          buildPayload={buildGalleryPayload}
        />
      )}

      {galleryPreviewArtifact && (
        <Modal
          open={Boolean(galleryPreviewArtifact)}
          onClose={() => setGalleryPreviewArtifact(null)}
          title="Review Preview"
          className="max-w-4xl border-white/[0.08] bg-[#0f0d17] text-white"
        >
          <div className="space-y-4">
            <div className="flex flex-wrap items-start justify-between gap-3 rounded-2xl border border-white/[0.06] bg-white/[0.025] p-4">
              <div className="flex min-w-0 items-center gap-3">
                <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-white/[0.045]">
                  {getKindIcon(galleryPreviewArtifact.fileKind)}
                </div>
                <div className="min-w-0">
                  <p className="truncate text-sm font-semibold text-white/80">
                    {galleryPreviewArtifact.fileName}
                  </p>
                  <p className="mt-0.5 text-[11px] text-white/30">
                    {new Date(galleryPreviewArtifact.createdAt).toLocaleString("de-DE")} ·{" "}
                    {formatFileSize(galleryPreviewArtifact.fileSize)}
                  </p>
                </div>
              </div>
              <div className="flex gap-2">
                <button
                  onClick={() => void handleGalleryDownload(galleryPreviewArtifact)}
                  className="rounded-xl border border-white/[0.07] bg-white/[0.035] px-3 py-2 text-xs font-semibold text-white/58 transition hover:bg-white/[0.06] hover:text-white"
                >
                  Download
                </button>
                <button
                  onClick={() => setGalleryShareArtifact(galleryPreviewArtifact)}
                  className={cn("rounded-xl border px-3 py-2 text-xs font-semibold transition", toneCfg.button)}
                >
                  Chat
                </button>
              </div>
            </div>

            <div className="overflow-hidden rounded-2xl border border-white/[0.06] bg-black/30">
              {galleryPreviewLoading ? (
                <div className="flex min-h-[320px] items-center justify-center text-sm text-white/35">
                  Preview wird geladen...
                </div>
              ) : galleryPreviewError ? (
                <div className="flex min-h-[220px] items-center justify-center px-6 text-center text-sm text-red-200/70">
                  {galleryPreviewError}
                </div>
              ) : galleryPreviewUrl && galleryPreviewFile?.type.startsWith("video/") ? (
                <video
                  className="max-h-[70vh] w-full bg-black"
                  controls
                  src={galleryPreviewUrl}
                />
              ) : galleryPreviewUrl && galleryPreviewFile?.type.startsWith("image/") ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img
                  alt={galleryPreviewArtifact.fileName}
                  className="max-h-[70vh] w-full object-contain"
                  src={galleryPreviewUrl}
                />
              ) : galleryPreviewUrl && galleryPreviewFile?.type === "application/pdf" ? (
                <iframe
                  className="h-[70vh] w-full bg-white"
                  src={galleryPreviewUrl}
                  title={galleryPreviewArtifact.fileName}
                />
              ) : (
                <div className="flex min-h-[220px] items-center justify-center px-6 text-center text-sm text-white/35">
                  Für diesen Dateityp gibt es keine direkte Preview. Download oder Chat funktionieren weiterhin.
                </div>
              )}
            </div>
          </div>
        </Modal>
      )}
    </div>
  );
}
