"use client";

import * as React from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription,
} from "@/components/ui/dialog";
import {
  AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent,
  AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import {
  Upload, Search, Trash2, ImageIcon, Video, FileText, Loader2, Copy, Check,
} from "lucide-react";
import { toast } from "sonner";

type MediaItem = {
  id: string;
  filename: string;
  originalName: string;
  url: string;
  mimeType: string;
  size: number;
  width?: number | null;
  height?: number | null;
  type: string;
  altText?: string | null;
  createdAt: string;
};

const TABS = [
  { value: "all", label: "All" },
  { value: "image", label: "Images" },
  { value: "video", label: "Videos" },
  { value: "document", label: "Documents" },
];

function fmtSize(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

export function MediaLibrary() {
  const [items, setItems] = React.useState<MediaItem[]>([]);
  const [loading, setLoading] = React.useState(false);
  const [uploading, setUploading] = React.useState(false);
  const [search, setSearch] = React.useState("");
  const [tab, setTab] = React.useState("all");
  const [selected, setSelected] = React.useState<MediaItem | null>(null);
  const [deleteTarget, setDeleteTarget] = React.useState<MediaItem | null>(null);
  const [deleting, setDeleting] = React.useState(false);
  const [altDraft, setAltDraft] = React.useState("");
  const [patchingAlt, setPatchingAlt] = React.useState(false);
  const [copied, setCopied] = React.useState(false);
  const fileRef = React.useRef<HTMLInputElement>(null);

  const fetchMedia = React.useCallback(async () => {
    setLoading(true);
    try {
      const params = new URLSearchParams();
      if (tab !== "all") params.set("type", tab);
      if (search) params.set("q", search);
      const res = await fetch(`/api/media?${params}`);
      const data = await res.json();
      setItems(data.items || []);
    } catch {
      toast.error("Failed to load media");
    } finally {
      setLoading(false);
    }
  }, [tab, search]);

  React.useEffect(() => {
    fetchMedia();
  }, [fetchMedia]);

  const handleUpload = async (files: FileList) => {
    if (!files.length) return;
    setUploading(true);
    try {
      const fd = new FormData();
      Array.from(files).forEach((f) => fd.append("files", f));
      const res = await fetch("/api/media", { method: "POST", body: fd });
      if (!res.ok) throw new Error();
      const data = await res.json();
      toast.success(`Uploaded ${data.items.length} file(s)`);
      fetchMedia();
    } catch {
      toast.error("Upload failed");
    } finally {
      setUploading(false);
      if (fileRef.current) fileRef.current.value = "";
    }
  };

  const openDetail = (item: MediaItem) => {
    setSelected(item);
    setAltDraft(item.altText || "");
  };

  const confirmDelete = async () => {
    if (!deleteTarget) return;
    setDeleting(true);
    try {
      const res = await fetch(`/api/media/${deleteTarget.id}`, { method: "DELETE" });
      if (!res.ok) throw new Error("Delete failed");
      toast.success("File deleted");
      setItems((prev) => prev.filter((i) => i.id !== deleteTarget.id));
      if (selected?.id === deleteTarget.id) setSelected(null);
      setDeleteTarget(null);
    } catch {
      toast.error("Delete failed");
    } finally {
      setDeleting(false);
    }
  };

  const saveAlt = async () => {
    if (!selected) return;
    setPatchingAlt(true);
    try {
      const res = await fetch(`/api/media/${selected.id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ altText: altDraft }),
      });
      if (!res.ok) throw new Error("Failed to update alt text");
      const data = await res.json();
      const updated = data.item as MediaItem;
      setSelected(updated);
      setItems((prev) => prev.map((i) => (i.id === updated.id ? updated : i)));
      toast.success("Alt text saved");
    } catch {
      toast.error("Update failed");
    } finally {
      setPatchingAlt(false);
    }
  };

  const copyUrl = async (url: string) => {
    try {
      await navigator.clipboard.writeText(url);
      setCopied(true);
      toast.success("URL copied to clipboard");
      setTimeout(() => setCopied(false), 1500);
    } catch {
      toast.error("Copy failed");
    }
  };

  return (
    <>
      <input
        ref={fileRef}
        type="file"
        multiple
        className="hidden"
        onChange={(e) => e.target.files && handleUpload(e.target.files)}
      />

      {/* Toolbar */}
      <div className="flex flex-col sm:flex-row gap-3 items-stretch sm:items-center justify-between mb-5">
        <Tabs value={tab} onValueChange={setTab} className="w-full sm:w-auto">
          <TabsList>
            {TABS.map((t) => (
              <TabsTrigger key={t.value} value={t.value}>{t.label}</TabsTrigger>
            ))}
          </TabsList>
        </Tabs>
        <div className="flex gap-2 w-full sm:w-auto">
          <div className="relative flex-1">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" />
            <Input
              placeholder="Search files..."
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              onKeyDown={(e) => e.key === "Enter" && fetchMedia()}
              className="pl-9 h-9"
            />
          </div>
          <Button
            onClick={() => fileRef.current?.click()}
            disabled={uploading}
            className="brand-gradient text-white"
          >
            {uploading ? <Loader2 className="size-4 mr-1.5 animate-spin" /> : <Upload className="size-4 mr-1.5" />}
            Upload
          </Button>
        </div>
      </div>

      {/* Grid */}
      {loading ? (
        <div className="grid place-items-center h-64 text-muted-foreground">
          <Loader2 className="size-6 animate-spin" />
        </div>
      ) : items.length === 0 ? (
        <div className="grid place-items-center h-64 text-muted-foreground text-sm border border-dashed rounded-2xl">
          <div className="flex flex-col items-center gap-2">
            <ImageIcon className="size-8 text-muted-foreground/40" />
            No media yet. Click &quot;Upload&quot; to add your first file.
          </div>
        </div>
      ) : (
        <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-3">
          {items.map((item) => (
            <div
              key={item.id}
              onClick={() => openDetail(item)}
              className="group relative rounded-xl overflow-hidden border-2 border-border hover:border-[var(--brand-royal)]/40 cursor-pointer transition-all"
            >
              <div className="aspect-square bg-muted grid place-items-center relative">
                {item.type === "image" ? (
                  <img src={item.url} alt={item.altText || item.originalName} className="size-full object-cover" />
                ) : item.type === "video" ? (
                  <video src={item.url} className="size-full object-cover" muted />
                ) : (
                  <FileText className="size-10 text-muted-foreground" />
                )}
                <button
                  onClick={(e) => { e.stopPropagation(); setDeleteTarget(item); }}
                  className="absolute bottom-1.5 right-1.5 grid place-items-center size-7 rounded-md bg-black/60 text-white opacity-0 group-hover:opacity-100 hover:bg-destructive transition-colors"
                  aria-label="Delete file"
                >
                  <Trash2 className="size-3.5" />
                </button>
              </div>
              <div className="p-2 bg-background">
                <div className="text-xs font-medium truncate">{item.originalName}</div>
                <div className="text-[10px] text-muted-foreground flex items-center gap-1">
                  {item.type === "image" ? <ImageIcon className="size-2.5" /> : item.type === "video" ? <Video className="size-2.5" /> : <FileText className="size-2.5" />}
                  {fmtSize(item.size)}
                </div>
              </div>
            </div>
          ))}
        </div>
      )}

      {/* Detail Dialog */}
      <Dialog open={!!selected} onOpenChange={(v) => !v && setSelected(null)}>
        <DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle className="truncate">{selected?.originalName}</DialogTitle>
            <DialogDescription>File details and management</DialogDescription>
          </DialogHeader>

          {selected && (
            <div className="grid md:grid-cols-2 gap-5">
              {/* Preview */}
              <div className="rounded-xl overflow-hidden border bg-muted grid place-items-center min-h-[240px]">
                {selected.type === "image" ? (
                  <img src={selected.url} alt={selected.altText || selected.originalName} className="size-full object-contain max-h-[420px]" />
                ) : selected.type === "video" ? (
                  <video src={selected.url} controls className="size-full max-h-[420px]" />
                ) : (
                  <div className="p-10 flex flex-col items-center gap-3 text-muted-foreground">
                    <FileText className="size-12" />
                    <span className="text-sm">No preview available</span>
                    <a href={selected.url} target="_blank" rel="noreferrer" className="text-[var(--brand-royal)] text-sm hover:underline">Open file</a>
                  </div>
                )}
              </div>

              {/* Meta */}
              <div className="space-y-4">
                <div className="space-y-2 text-sm">
                  <div className="flex justify-between gap-3">
                    <span className="text-muted-foreground">Type</span>
                    <span className="font-medium font-mono text-xs">{selected.mimeType}</span>
                  </div>
                  {selected.width && selected.height && (
                    <div className="flex justify-between gap-3">
                      <span className="text-muted-foreground">Dimensions</span>
                      <span className="font-medium">{selected.width} × {selected.height}px</span>
                    </div>
                  )}
                  <div className="flex justify-between gap-3">
                    <span className="text-muted-foreground">Size</span>
                    <span className="font-medium">{fmtSize(selected.size)}</span>
                  </div>
                  <div className="flex justify-between gap-3">
                    <span className="text-muted-foreground">Uploaded</span>
                    <span className="font-medium">{new Date(selected.createdAt).toLocaleString("en-PK")}</span>
                  </div>
                </div>

                <div className="space-y-1.5">
                  <Label>URL</Label>
                  <div className="flex gap-2">
                    <Input readOnly value={selected.url} className="font-mono text-xs h-9" />
                    <Button
                      type="button"
                      size="sm"
                      variant="outline"
                      onClick={() => copyUrl(selected.url)}
                      className="shrink-0"
                    >
                      {copied ? <Check className="size-3.5" /> : <Copy className="size-3.5" />}
                    </Button>
                  </div>
                </div>

                <div className="space-y-1.5">
                  <Label>Alt Text</Label>
                  <Textarea
                    rows={3}
                    value={altDraft}
                    onChange={(e) => setAltDraft(e.target.value)}
                    placeholder="Describe this file for accessibility and SEO"
                  />
                  <Button
                    type="button"
                    size="sm"
                    onClick={saveAlt}
                    disabled={patchingAlt}
                    className="brand-gradient text-white"
                  >
                    {patchingAlt ? <Loader2 className="size-3.5 mr-1.5 animate-spin" /> : null}
                    Save Alt Text
                  </Button>
                </div>

                <div className="pt-3 border-t">
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    className="text-destructive hover:text-destructive"
                    onClick={() => setDeleteTarget(selected)}
                  >
                    <Trash2 className="size-4 mr-1.5" /> Delete File
                  </Button>
                </div>
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>

      {/* Delete confirm */}
      <AlertDialog open={!!deleteTarget} onOpenChange={(v) => !v && !deleting && setDeleteTarget(null)}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete this file?</AlertDialogTitle>
            <AlertDialogDescription>
              This will permanently delete <span className="font-medium">{deleteTarget?.originalName}</span> from your media library. This action cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={deleting}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              onClick={(e) => { e.preventDefault(); confirmDelete(); }}
              disabled={deleting}
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
            >
              {deleting ? <Loader2 className="size-4 mr-1.5 animate-spin" /> : <Trash2 className="size-4 mr-1.5" />}
              Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  );
}
