"use client";

import { useRef, useState, type ChangeEvent } from "react";
import { useRouter } from "next/navigation";
import { Button } from "@/components/ui/button";
import { FileInput } from "@/components/ui/input";
import { useConfirmDialog } from "@/components/ui/confirm-dialog";
import { useToast } from "@/components/ui/toast";
import { clientFetch } from "@/lib/api/client";

const MAX_MEDIA_SLOT_BYTES = 5 * 1024 * 1024;
const ACCEPTED_MEDIA_SLOT_TYPES = ["image/jpeg", "image/png", "image/webp"];

/**
 * Single-image upload/replace/delete slot — a real file upload (multipart
 * POST to `endpoint`, create-or-replace) backed by `Storage::disk('public')`
 * on the Laravel side, never a pasted URL. Shared by event thumbnail/banner,
 * general-settings logos, and signature brand partner logos.
 *
 * Deliberately has no `<form>` of its own (upload is triggered by a plain
 * button `onClick`, not native form submission) — several call sites (e.g.
 * GeneralSettingsForm) render this inside their own `<form>`, and a nested
 * `<form>` is invalid HTML that breaks hydration.
 */
export function MediaSlot({
  label,
  fieldName,
  endpoint,
  current,
  hint,
}: {
  label: string;
  fieldName: string;
  endpoint: string;
  current: string | null;
  hint: string;
}) {
  const router = useRouter();
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [isDeleting, setIsDeleting] = useState(false);
  const { confirm, dialog } = useConfirmDialog();
  const { toast } = useToast();

  function handleFileChange(changeEvent: ChangeEvent<HTMLInputElement>) {
    setError(null);
    const file = changeEvent.target.files?.[0];
    if (!file) {
      setSelectedFile(null);
      return;
    }

    if (!ACCEPTED_MEDIA_SLOT_TYPES.includes(file.type)) {
      setError("Format must be JPG, PNG, or WEBP.");
      changeEvent.target.value = "";
      setSelectedFile(null);
      return;
    }
    if (file.size > MAX_MEDIA_SLOT_BYTES) {
      setError("Maximum image size is 5MB.");
      changeEvent.target.value = "";
      setSelectedFile(null);
      return;
    }

    setSelectedFile(file);
  }

  async function handleUpload() {
    if (!selectedFile) return;
    setError(null);
    setIsSubmitting(true);

    const formData = new FormData();
    formData.append(fieldName, selectedFile);

    const res = await clientFetch(endpoint, { method: "POST", body: formData });
    setIsSubmitting(false);
    const body = await res.json().catch(() => null);

    if (!res.ok) {
      const message = body?.errors?.[fieldName]?.[0] ?? body?.message ?? "Failed to upload.";
      setError(message);
      toast(message, "error");
      return;
    }

    setSelectedFile(null);
    if (fileInputRef.current) fileInputRef.current.value = "";
    toast(`${label} uploaded successfully.`, "success");
    router.refresh();
  }

  async function handleDelete() {
    if (!(await confirm(`Delete ${label.toLowerCase()}?`))) return;

    setError(null);
    setIsDeleting(true);
    const res = await clientFetch(endpoint, { method: "DELETE" });
    setIsDeleting(false);
    const body = await res.json().catch(() => null);

    if (!res.ok) {
      const message = body?.message ?? "Failed to delete.";
      setError(message);
      toast(message, "error");
      return;
    }
    toast(`${label} deleted successfully.`, "success");
    router.refresh();
  }

  return (
    <div>
      {dialog}
      <p className="text-sm font-medium">{label}</p>
      <p className="text-xs text-kolabora-neutral-dark/70">{hint}</p>
      {current ? (
        <div className="mt-2 flex items-start gap-3">
          {/* eslint-disable-next-line @next/next/no-img-element -- organizer-uploaded file, not on next/image allowlist */}
          <img src={current} alt={label} className="h-32 w-48 rounded-lg object-cover" />
          <Button type="button" variant="danger" size="sm" onClick={handleDelete} loading={isDeleting}>
            Delete
          </Button>
        </div>
      ) : (
        <p className="mt-2 text-sm text-kolabora-neutral-dark/70">No {label.toLowerCase()} yet.</p>
      )}
      <div className="mt-3 flex flex-col items-start gap-2 sm:flex-row sm:items-center">
        <FileInput
          ref={fileInputRef}
          name={fieldName}
          accept="image/jpeg,image/png,image/webp"
          onChange={handleFileChange}
          className="min-w-0 max-w-full"
        />
        <Button type="button" size="sm" loading={isSubmitting} disabled={!selectedFile} onClick={handleUpload}>
          {current ? "Replace" : "Upload"}
        </Button>
      </div>
      {error && <p className="mt-1 text-sm text-red-600">{error}</p>}
    </div>
  );
}
