"use client";

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

const VARIANT_MAP: Record<"primary" | "danger" | "default", ButtonVariant> = {
  primary: "primary",
  danger: "danger",
  default: "secondary",
};

/**
 * ActionButton is reused for many different endpoints (suspend, reinstate,
 * promote/demote-organizer, publish, approve, ...), so it can't know a
 * specific field name to read a Laravel ValidationException's message from
 * — unlike ReasonAction, which always targets `errors.reason`. This reads
 * whichever field the backend actually populated, so a specific rejection
 * reason (e.g. "Akun ini bukan Organizer.") surfaces instead of the generic
 * top-level `message`.
 */
function firstErrorMessage(body: unknown): string | undefined {
  if (typeof body !== "object" || body === null || !("errors" in body)) return undefined;
  const errors = (body as { errors?: unknown }).errors;
  if (typeof errors !== "object" || errors === null) return undefined;
  const firstValue = Object.values(errors as Record<string, unknown>)[0];
  return Array.isArray(firstValue) ? firstValue[0] : undefined;
}

export function ActionButton({
  endpoint,
  label,
  variant = "default",
  confirmMessage,
  method = "POST",
}: {
  endpoint: string;
  label: string;
  variant?: "primary" | "danger" | "default";
  confirmMessage?: string;
  method?: "POST" | "DELETE";
}) {
  const router = useRouter();
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const { confirm, dialog } = useConfirmDialog();
  const { toast } = useToast();

  async function handleClick() {
    if (confirmMessage && !(await confirm(confirmMessage))) return;

    setError(null);
    setIsSubmitting(true);
    const res = await clientFetch(endpoint, { method });
    setIsSubmitting(false);

    const body = await res.json().catch(() => null);
    if (!res.ok) {
      const message = firstErrorMessage(body) ?? body?.message ?? "Action failed.";
      setError(message);
      toast(message, "error");
      return;
    }
    toast(`${label} successful.`, "success");
    router.refresh();
  }

  return (
    <div className="flex flex-col items-start gap-1">
      {dialog}
      <Button type="button" variant={VARIANT_MAP[variant]} size="sm" onClick={handleClick} loading={isSubmitting}>
        {label}
      </Button>
      {error && <p className="text-xs text-red-600">{error}</p>}
    </div>
  );
}
