"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import imageCompression from "browser-image-compression";
import { Upload, X } from '@/lib/icons';
import { toast } from "sonner";
import { cn } from "@/lib/utils";

import { deletePropertyImageAction } from "@/lib/appwrite/storage-actions";
import { getPropertyImagePreviewUrl } from "@/lib/appwrite/storage-utils";

type UploadingFile = { uid: string; name: string; progress: number; phase: "compressing" | "uploading" };

interface PropertyImageUploaderProps {
  name: string;
  initialImageIds?: string[];
  onChangeIds?: (ids: string[]) => void;
  onDeleteImage?: (fileId: string) => Promise<boolean>;
  maxImages?: number;
  isOwner?: boolean;
}

export function PropertyImageUploader({ name, initialImageIds = [], onChangeIds, onDeleteImage, maxImages, isOwner }: PropertyImageUploaderProps) {
  const [imageIds, setImageIds] = useState<string[]>(initialImageIds);
  const [queue, setQueue] = useState<UploadingFile[]>([]);
  const [dragging, setDragging] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    onChangeIds?.(imageIds);
  }, [imageIds]); // eslint-disable-line react-hooks/exhaustive-deps

  function updateIds(updater: (prev: string[]) => string[]) {
    setImageIds(updater);
  }

  const uploadOne = useCallback(async (file: File) => {
    if (!file.type.startsWith("image/")) {
      toast.error(`${file.name}: Sadece görsel dosyaları desteklenir.`);
      return;
    }
    if (file.size > 50 * 1024 * 1024) {
      toast.error(`${file.name}: 50 MB sınırını aşıyor.`);
      return;
    }
    if (maxImages !== undefined && imageIds.length >= maxImages) {
      toast.error(
        isOwner
          ? `Ücretsiz planda ilan başına en fazla ${maxImages} fotoğraf ekleyebilirsiniz. Pro'ya geçerek limitsiz yükleyin.`
          : "Bu çalışma alanı fotoğraf limitine ulaştı. Yöneticinizle iletişime geçin.",
      );
      return;
    }

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

    let compressed: File;
    try {
      compressed = await imageCompression(file, {
        maxSizeMB: 1.5,
        maxWidthOrHeight: 1920,
        useWebWorker: true,
        initialQuality: 0.85,
        fileType: file.type === "image/png" ? "image/png" : "image/jpeg",
      });
    } catch {
      setQueue((q) => q.filter((u) => u.uid !== uid));
      toast.error(`${file.name}: Sıkıştırma başarısız.`);
      return;
    }

    setQueue((q) => q.map((u) => (u.uid === uid ? { ...u, phase: "uploading", progress: 0 } : u)));

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

    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, phase: "uploading", progress: pct } : u)));
      }
    });

    xhr.addEventListener("load", () => {
      setQueue((q) => q.filter((u) => u.uid !== uid));
      try {
        const res = JSON.parse(xhr.responseText) as { ok: boolean; fileId?: string; error?: string };
        if (res.ok && res.fileId) {
          updateIds((prev) => [...prev, res.fileId!]);
        } 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/properties/images");
    xhr.send(fd);
  }, [imageIds, maxImages]); // eslint-disable-line react-hooks/exhaustive-deps

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

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

  async function handleDelete(fileId: string) {
    if (onDeleteImage) {
      const ok = await onDeleteImage(fileId);
      if (ok) updateIds((prev) => prev.filter((id) => id !== fileId));
      return;
    }
    const result = await deletePropertyImageAction(fileId);
    if (result.ok) {
      updateIds((prev) => prev.filter((id) => id !== fileId));
    } else {
      toast.error(result.error ?? "Fotoğraf silinemedi");
    }
  }

  const busy = queue.length > 0;

  return (
    <div className="space-y-3">
      <input type="hidden" name={name} value={JSON.stringify(imageIds)} />

      {/* Drop zone */}
      <div
        role="button"
        tabIndex={0}
        onClick={() => inputRef.current?.click()}
        onKeyDown={(e) => e.key === "Enter" && inputRef.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-2 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",
        )}
      >
        <Upload className={cn("size-6", dragging ? "text-primary" : "text-muted-foreground")} />
        <p className="text-sm">
          <span className="font-medium text-primary">Fotoğraf seç</span>
          <span className="text-muted-foreground"> veya buraya sürükle</span>
        </p>
        <p className="text-xs text-muted-foreground">PNG, JPG, WebP — otomatik sıkıştırılır, birden fazla seçilebilir</p>
      </div>

      <input
        ref={inputRef}
        type="file"
        accept="image/*"
        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">
            <span className="truncate text-xs font-medium">{u.name}</span>
            <span className="shrink-0 text-xs text-muted-foreground tabular-nums">
              {u.phase === "compressing"
                ? "Sıkıştırılıyor…"
                : u.progress < 100
                  ? `%${u.progress}`
                  : "İşleniyor…"}
            </span>
          </div>
          <div className="h-1.5 w-full overflow-hidden rounded-full bg-muted">
            <div
              className={cn(
                "h-full rounded-full transition-all duration-200",
                u.phase === "compressing" ? "animate-pulse bg-amber-400 w-full" : "bg-primary",
              )}
              style={u.phase === "uploading" ? { width: `${u.progress}%` } : undefined}
            />
          </div>
        </div>
      ))}

      {/* Thumbnail grid */}
      {imageIds.length > 0 && (
        <div className="grid grid-cols-3 gap-2">
          {imageIds.map((id) => (
            <div key={id} className="relative aspect-video overflow-hidden rounded-md border bg-muted">
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img
                src={getPropertyImagePreviewUrl(id, 400, 300)}
                alt=""
                className="h-full w-full object-cover"
              />
              <button
                type="button"
                onClick={() => handleDelete(id)}
                disabled={busy}
                className="absolute right-1 top-1 flex size-6 items-center justify-center rounded-full bg-black/50 text-white transition-colors hover:bg-red-500"
              >
                <X className="size-3" />
              </button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
