"use client";

import { useCallback, useEffect, useRef, useState, useTransition } from "react";
import { Loader2, Paperclip, Trash2, UploadCloud } from "lucide-react";
import { toast } from "sonner";

import { Label } from "@/components/ui/label";
import { Progress } from "@/components/ui/progress";
import {
  deleteAttachmentAction,
  fetchAttachmentsAction,
  type AttachmentItem,
} from "@/lib/appwrite/attachment-actions";
import { cn } from "@/lib/utils";

type UploadingFile = {
  uid: string;
  name: string;
  size: number;
  progress: number;
};

type Props = {
  entityType: "service" | "customer_software";
  entityId: string;
};

function formatBytes(n: number): string {
  if (n < 1024) return `${n} B`;
  if (n < 1048576) return `${(n / 1024).toFixed(1)} KB`;
  return `${(n / 1048576).toFixed(1)} MB`;
}

export function AttachmentsPanel({ entityType, entityId }: Props) {
  const [attachments, setAttachments] = useState<AttachmentItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [queue, setQueue] = useState<UploadingFile[]>([]);
  const [dragging, setDragging] = useState(false);
  const [, startDelete] = useTransition();
  const fileRef = useRef<HTMLInputElement>(null);

  const load = useCallback(async () => {
    setLoading(true);
    const data = await fetchAttachmentsAction(entityType, entityId);
    setAttachments(data);
    setLoading(false);
  }, [entityType, entityId]);

  useEffect(() => {
    load();
  }, [load]);

  const uploadOne = useCallback(
    (file: File) => {
      if (file.size > 20 * 1024 * 1024) {
        toast.error(`${file.name}: 20 MB sınırını aşıyor.`);
        return;
      }

      const uid = crypto.randomUUID();
      setQueue((q) => [...q, { uid, name: file.name, size: file.size, progress: 0 }]);

      const fd = new FormData();
      fd.append("file", file);
      fd.append("entityType", entityType);
      fd.append("entityId", entityId);

      const xhr = new XMLHttpRequest();

      xhr.upload.addEventListener("progress", (e) => {
        if (e.lengthComputable) {
          const pct = Math.round((e.loaded / e.total) * 100);
          setQueue((q) => q.map((u) => (u.uid === uid ? { ...u, progress: pct } : u)));
        }
      });

      xhr.addEventListener("load", () => {
        setQueue((q) => q.filter((u) => u.uid !== uid));
        try {
          const res = JSON.parse(xhr.responseText) as { ok: boolean; error?: string };
          if (res.ok) {
            load();
          } else {
            toast.error(res.error ?? "Yükleme başarısız.");
          }
        } catch {
          toast.error("Yükleme başarısız.");
        }
      });

      xhr.addEventListener("error", () => {
        setQueue((q) => q.filter((u) => u.uid !== uid));
        toast.error(`${file.name}: Bağlantı hatası.`);
      });

      xhr.open("POST", "/api/attachments");
      xhr.send(fd);
    },
    [entityType, entityId, load],
  );

  const handleFiles = useCallback(
    (list: FileList | null) => {
      if (!list) return;
      Array.from(list).forEach(uploadOne);
      if (fileRef.current) fileRef.current.value = "";
    },
    [uploadOne],
  );

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setDragging(false);
    handleFiles(e.dataTransfer.files);
  };

  const handleDelete = (a: AttachmentItem) => {
    startDelete(async () => {
      const fd = new FormData();
      fd.set("attachmentId", a.id);
      const result = await deleteAttachmentAction(fd);
      if (result.ok) {
        setAttachments((prev) => prev.filter((x) => x.id !== a.id));
        toast.success("Dosya silindi.");
      } else {
        toast.error(result.error ?? "Silme başarısız.");
      }
    });
  };

  const hasItems = attachments.length > 0 || queue.length > 0;

  return (
    <div className="grid gap-2">
      <Label>Ekler</Label>

      {/* Drop zone */}
      <div
        role="button"
        tabIndex={0}
        onClick={() => fileRef.current?.click()}
        onKeyDown={(e) => e.key === "Enter" && fileRef.current?.click()}
        onDragOver={(e) => {
          e.preventDefault();
          setDragging(true);
        }}
        onDragLeave={() => setDragging(false)}
        onDrop={handleDrop}
        className={cn(
          "flex cursor-pointer select-none flex-col items-center justify-center gap-1.5 rounded-lg border-2 border-dashed px-4 py-5 text-center transition-colors",
          dragging
            ? "border-primary bg-primary/5"
            : "border-border hover:border-primary/40 hover:bg-muted/30",
        )}
      >
        <UploadCloud
          className={cn("size-7", dragging ? "text-primary" : "text-muted-foreground")}
        />
        <p className="text-sm">
          <span className="text-primary font-medium">Dosya seç</span>
          <span className="text-muted-foreground"> veya buraya sürükle</span>
        </p>
        <p className="text-muted-foreground text-xs">Maks. 20 MB — birden fazla dosya eklenebilir</p>
      </div>

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

      {/* Upload progress rows */}
      {queue.map((u) => (
        <div key={u.uid} className="space-y-1.5 rounded-lg border px-3 py-2.5">
          <div className="flex items-center justify-between gap-2">
            <div className="flex min-w-0 items-center gap-1.5">
              <Loader2 className="text-primary size-3.5 shrink-0 animate-spin" />
              <span className="truncate text-xs font-medium">{u.name}</span>
            </div>
            <span className="text-muted-foreground shrink-0 text-xs">
              {u.progress < 100 ? `${u.progress}%` : "İşleniyor..."}
            </span>
          </div>
          <Progress value={u.progress} className="h-1.5" />
        </div>
      ))}

      {/* Existing files */}
      {loading ? (
        <div className="text-muted-foreground flex items-center gap-2 py-1 text-xs">
          <Loader2 className="size-3 animate-spin" />
          Yükleniyor...
        </div>
      ) : !hasItems ? (
        <p className="text-muted-foreground py-0.5 text-xs">Henüz ek dosya yok.</p>
      ) : (
        <div className="space-y-1">
          {attachments.map((a) => (
            <div
              key={a.id}
              className="bg-muted/30 flex items-center gap-2 rounded-md border px-2.5 py-2"
            >
              <Paperclip className="text-muted-foreground size-3.5 shrink-0" />
              <a
                href={`/api/files/${a.id}`}
                download={a.name}
                className="min-w-0 flex-1 truncate text-xs hover:underline"
                title={a.name}
              >
                {a.name}
              </a>
              <span className="text-muted-foreground shrink-0 text-xs tabular-nums">
                {formatBytes(a.size)}
              </span>
              <button
                type="button"
                onClick={() => handleDelete(a)}
                className="text-muted-foreground hover:text-destructive ml-0.5 shrink-0 transition-colors"
                title="Sil"
              >
                <Trash2 className="size-3.5" />
              </button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
