"use client";

import { useState } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useT } from "@/i18n";
import { useCan } from "@/features/auth/use-can";
import { friendlyErrorMessage } from "@/lib/errors";
import { useFieldErrors } from "@/lib/use-field-errors";
import { queryKeys } from "@/lib/query-keys";
import {
  approveStoreClient,
  rejectStoreClient,
  suspendStoreClient,
} from "@/services/store-clients";
import type { StoreClient } from "@/types/store";

type Decision = "approve" | "reject" | "suspend";

/**
 * The decision on a store's application.
 *
 * Which buttons appear is driven by the transitions the backend actually allows, rather than by
 * showing everything and letting the API refuse. A button that answers 409 teaches somebody the
 * rules one mistake at a time.
 *
 *   pending   → approve, reject
 *   approved  → suspend
 *   suspended → approve (this is the unpause), reject
 *   rejected  → approve
 */
export function StoreReviewActions({ store }: { store: StoreClient }) {
  const t = useT();
  const { can } = useCan();
  const queryClient = useQueryClient();

  const [open, setOpen] = useState<Decision | null>(null);
  const [note, setNote] = useState("");
  // The note is the only field here; the store's own state is not something this box can fix.
  const fields = useFieldErrors({ only: ["note", "review_note"] });

  const canReview = can("store_clients.review");
  const canManage = can("store_clients.manage");

  const refresh = () => {
    void queryClient.invalidateQueries({ queryKey: queryKeys.storeClients.detail(store.uuid) });
    void queryClient.invalidateQueries({ queryKey: ["store-clients", "list"] });
  };

  const mutation = useMutation({
    mutationFn: async (decision: Decision) => {
      if (decision === "approve") return approveStoreClient(store.uuid, note || undefined);
      if (decision === "reject") return rejectStoreClient(store.uuid, note);
      return suspendStoreClient(store.uuid, note);
    },
    onSuccess: (_data, decision) => {
      toast.success(
        decision === "approve"
          ? t("stores.approved")
          : decision === "reject"
            ? t("stores.rejected")
            : t("stores.suspended"),
      );
      setOpen(null);
      setNote("");
      refresh();
    },
    onMutate: fields.reset,
    onError: (error) => {
      // A note the server judges too short lands under the box; "already approved" is not a field
      // and stays a toast.
      if (!fields.capture(error)) toast.error(friendlyErrorMessage(error, t));
    },
  });

  const canApprove = ["pending", "suspended", "rejected"].includes(store.status);
  const canReject = ["pending", "suspended"].includes(store.status);
  const canSuspend = store.status === "approved";

  // A rejection or a suspension is what a shop rings up about, so the API insists on a reason.
  const noteRequired = open === "reject" || open === "suspend";

  const copy: Record<Decision, { title: string; body: string; confirm: string }> = {
    approve: {
      title: t("stores.approveTitle"),
      body: t("stores.approveBody"),
      confirm: store.status === "suspended" ? t("stores.reinstate") : t("stores.approve"),
    },
    reject: {
      title: t("stores.rejectTitle"),
      body: t("stores.rejectBody"),
      confirm: t("stores.reject"),
    },
    suspend: {
      title: t("stores.suspendTitle"),
      body: t("stores.suspendBody"),
      confirm: t("stores.suspend"),
    },
  };

  return (
    <>
      <div className="flex flex-wrap items-center gap-2">
        {canReview && canApprove ? (
          <Button
            onClick={() => setOpen("approve")}
            title={store.status === "suspended" ? t("stores.reinstateHint") : undefined}
          >
            {store.status === "suspended" ? t("stores.reinstate") : t("stores.approve")}
          </Button>
        ) : null}

        {canReview && canReject ? (
          <Button variant="outline" onClick={() => setOpen("reject")}>
            {t("stores.reject")}
          </Button>
        ) : null}

        {canManage && canSuspend ? (
          <Button variant="outline" onClick={() => setOpen("suspend")}>
            {t("stores.suspend")}
          </Button>
        ) : null}
      </div>

      <Dialog open={open !== null} onOpenChange={(next) => (next ? null : setOpen(null))}>
        <DialogContent>
          {open ? (
            <>
              <DialogHeader>
                <DialogTitle>{copy[open].title}</DialogTitle>
                <DialogDescription>{copy[open].body}</DialogDescription>
              </DialogHeader>

              <div className="space-y-2">
                <Label htmlFor="review-note">
                  {t("stores.reviewNote")}
                  {!noteRequired ? ` (${t("common.optional")})` : ""}
                </Label>
                <Input
                  id="review-note"
                  value={note}
                  onChange={(e) => setNote(e.target.value)}
                  maxLength={255}
                />
                {fields.get("note") ?? fields.get("review_note") ? (
                  <p className="text-xs text-destructive">
                    {fields.get("note") ?? fields.get("review_note")}
                  </p>
                ) : null}
                {noteRequired ? (
                  <p className="text-xs text-muted-foreground">{t("stores.noteRequired")}</p>
                ) : null}
              </div>

              <DialogFooter>
                <Button variant="ghost" onClick={() => setOpen(null)}>
                  {t("common.cancel")}
                </Button>
                <Button
                  onClick={() => mutation.mutate(open)}
                  disabled={mutation.isPending || (noteRequired && note.trim() === "")}
                >
                  {mutation.isPending ? t("common.saving") : copy[open].confirm}
                </Button>
              </DialogFooter>
            </>
          ) : null}
        </DialogContent>
      </Dialog>
    </>
  );
}
