"use client";

import { useRef, useState } from "react";
import Image from "next/image";
import { getSupabaseClient } from "@/lib/supabase";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { GripVertical, Loader2, Plus, Star, StarOff, Trash2, Upload } from "lucide-react";
import type { ProductImageItem } from "@/lib/product-images";
import { encolherParaUpload } from "@/lib/fotos/encolher";

interface ProductImageGalleryEditorProps {
  images: ProductImageItem[];
  onChange: (images: ProductImageItem[]) => void;
  bucket?: string;
  folder?: string;
  disabled?: boolean;
}

function reorderImages(images: ProductImageItem[], fromIndex: number, toIndex: number) {
  if (fromIndex === toIndex || fromIndex < 0 || toIndex < 0) return images;
  if (fromIndex >= images.length || toIndex >= images.length) return images;
  const next = images.slice();
  const [moved] = next.splice(fromIndex, 1);
  next.splice(toIndex, 0, moved);
  return next.map((image, index) => ({ ...image, sort_order: index }));
}

function ensurePrimary(images: ProductImageItem[]) {
  if (!images.length) return [];
  const hasPrimary = images.some((image) => image.is_primary);
  if (hasPrimary) return images;
  const [first, ...rest] = images;
  return [{ ...first, is_primary: true }, ...rest.map((item) => ({ ...item, is_primary: false }))];
}

export function ProductImageGalleryEditor({
  images,
  onChange,
  bucket = "products",
  folder = "products",
  disabled = false,
}: ProductImageGalleryEditorProps) {
  const fileInputRef = useRef<HTMLInputElement | null>(null);
  const [uploading, setUploading] = useState(false);
  const [draggingIndex, setDraggingIndex] = useState<number | null>(null);
  const [dropTargetIndex, setDropTargetIndex] = useState<number | null>(null);
  /* O aviso mora aqui, embaixo do botão de enviar: a caixinha do navegador
     para de aparecer depois de algumas seguidas. */
  const [erro, setErro] = useState<string | null>(null);

  async function uploadFiles(fileList: FileList | null) {
    if (!fileList?.length) return;
    setUploading(true);
    setErro(null);
    const currentLength = images.length;
    const created: ProductImageItem[] = [];
    try {
      const supabase = getSupabaseClient();

      for (let index = 0; index < fileList.length; index += 1) {
        /* Encolhida no navegador antes de subir: no máximo 1600 px, em WebP.
           A foto do celular de 4 MB vira uns 200 KB. */
        const file = await encolherParaUpload(fileList[index]);
        const extension = file.name.split(".").pop() || "png";
        const path = `${folder ? `${folder}/` : ""}${crypto.randomUUID()}_${Date.now()}.${extension}`;

        const { error: uploadError } = await supabase.storage
          .from(bucket)
          .upload(path, file, { contentType: file.type || undefined });
        if (uploadError) throw uploadError;

        const { data: publicUrlData } = supabase.storage.from(bucket).getPublicUrl(path);
        const imageUrl = publicUrlData.publicUrl;
        if (!imageUrl) continue;

        created.push({
          id: crypto.randomUUID(),
          image_url: imageUrl,
          sort_order: currentLength + created.length,
          is_primary: currentLength === 0 && created.length === 0,
        });
      }

      if (created.length) {
        onChange(ensurePrimary([...images, ...created]));
      }
    } catch (error) {
      console.error("Erro ao enviar imagens:", error);
      /* As que já subiram antes do erro entram na galeria: estão no
         armazenamento e se perderiam se ficassem de fora. */
      if (created.length) {
        onChange(ensurePrimary([...images, ...created]));
      }
      setErro(
        created.length
          ? "Algumas imagens não foram enviadas. As que subiram já estão na galeria."
          : "Não foi possível enviar as imagens. Tente de novo."
      );
    } finally {
      setUploading(false);
      if (fileInputRef.current) fileInputRef.current.value = "";
    }
  }

  function setPrimary(targetId: string) {
    const next = images.map((image) => ({
      ...image,
      is_primary: image.id === targetId,
    }));
    onChange(ensurePrimary(next));
  }

  function removeImage(targetId: string) {
    const next = images
      .filter((image) => image.id !== targetId)
      .map((image, index) => ({ ...image, sort_order: index }));
    onChange(ensurePrimary(next));
  }

  function moveImage(fromIndex: number, toIndex: number) {
    const reordered = reorderImages(images, fromIndex, toIndex);
    onChange(ensurePrimary(reordered));
  }

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between gap-3">
        <p className="text-xs text-[var(--ks-color-text-soft)]">
          Adicione várias fotos, defina a principal e arraste para ordenar.
        </p>
        <div className="flex items-center gap-2">
          <input
            ref={fileInputRef}
            type="file"
            accept="image/*"
            multiple
            onChange={(event) => uploadFiles(event.target.files)}
            className="hidden"
            disabled={disabled || uploading}
          />
          <Button
            type="button"
            size="sm"
            variant="ghost"
            onClick={() => fileInputRef.current?.click()}
            disabled={disabled || uploading}
            icon={uploading ? <Loader2 className="w-4 h-4 animate-spin" /> : <Upload size={14} />}
          >
            {uploading ? "Enviando..." : "Enviar imagens"}
          </Button>
        </div>
      </div>

      {erro ? (
        <p role="alert" className="text-xs font-medium text-rose-600">
          {erro}
        </p>
      ) : null}

      {images.length === 0 ? (
        <div className="rounded-xl border border-dashed border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-soft)] px-4 py-8 text-center">
          <p className="text-sm text-[var(--ks-color-text-muted)]">Nenhuma imagem cadastrada.</p>
          <button
            type="button"
            onClick={() => fileInputRef.current?.click()}
            disabled={disabled || uploading}
            className="mt-3 inline-flex items-center gap-2 rounded-full border border-[rgba(198,203,224,0.9)] bg-white px-3 py-1.5 text-xs font-medium text-[var(--ks-color-primary)]"
          >
            <Plus size={12} />
            Adicionar primeira imagem
          </button>
        </div>
      ) : (
        <div className="grid grid-cols-2 gap-3 sm:grid-cols-3">
          {images.map((image, index) => (
            <div
              key={image.id}
              draggable={!disabled}
              onDragStart={() => setDraggingIndex(index)}
              onDragOver={(event) => {
                event.preventDefault();
                setDropTargetIndex(index);
              }}
              onDragLeave={() => setDropTargetIndex((current) => (current === index ? null : current))}
              onDrop={(event) => {
                event.preventDefault();
                if (draggingIndex === null) return;
                moveImage(draggingIndex, index);
                setDraggingIndex(null);
                setDropTargetIndex(null);
              }}
              onDragEnd={() => {
                setDraggingIndex(null);
                setDropTargetIndex(null);
              }}
              className={cn(
                "group rounded-xl border bg-white p-2 shadow-sm transition-colors",
                image.is_primary
                  ? "border-[var(--ks-color-primary)]"
                  : "border-[var(--ks-color-border-subtle)]",
                dropTargetIndex === index ? "ring-2 ring-[var(--ks-color-primary)]/30" : ""
              )}
            >
              <div className="relative aspect-square overflow-hidden rounded-lg bg-slate-50">
                <Image
                  src={image.image_url}
                  alt={`Imagem ${index + 1}`}
                  fill
                  className="object-cover"
                  sizes="(max-width: 768px) 50vw, 20vw"
                  unoptimized
                />
                <div className="absolute left-2 top-2 inline-flex items-center gap-1 rounded-full bg-black/50 px-2 py-1 text-[10px] font-medium text-white">
                  <GripVertical size={10} />
                  {index + 1}
                </div>
              </div>

              <div className="mt-2 flex items-center justify-between gap-2">
                <button
                  type="button"
                  onClick={() => setPrimary(image.id)}
                  disabled={disabled}
                  className={cn(
                    "inline-flex items-center gap-1 rounded-full px-2 py-1 text-[10px] font-semibold transition-colors",
                    image.is_primary
                      ? "bg-amber-50 text-amber-700"
                      : "bg-slate-100 text-slate-600 hover:bg-slate-200"
                  )}
                >
                  {image.is_primary ? <Star size={10} /> : <StarOff size={10} />}
                  {image.is_primary ? "Principal" : "Definir principal"}
                </button>

                <button
                  type="button"
                  onClick={() => removeImage(image.id)}
                  disabled={disabled}
                  className="inline-flex h-7 w-7 items-center justify-center rounded-full bg-rose-50 text-rose-600 hover:bg-rose-100"
                  aria-label="Remover imagem"
                >
                  <Trash2 size={12} />
                </button>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
