"use client";

import { useState } from "react";
import { useMutation } 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, Textarea } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useT } from "@/i18n";
import { friendlyErrorMessage } from "@/lib/errors";
import { useFieldErrors } from "@/lib/use-field-errors";
import { updateSettlement } from "@/services/settlements";
import type { Settlement, SettlementInput } from "@/types/store";

/**
 * Correct a **draft** settlement.
 *
 * Two things this form does not do, both deliberate:
 *
 *  - **It does not send a partial update.** The server validates the whole payload, so every field
 *    goes with every save; a partial body is refused with a 422 that reads like a missing field.
 *  - **It does not recompute the net amount.** It is allowed to differ from cash − fees — an
 *    adjustment, a rounding, a dispute settled halfway — and what is recorded is what somebody
 *    agreed to pay, not what arithmetic implies.
 *
 * Only a draft reaches this dialog. A settled row is a record both sides hold, and the server
 * answers 409 rather than editing one.
 */
export function EditSettlementDialog({
  settlement,
  open,
  onOpenChange,
  onSaved,
}: {
  settlement: Settlement;
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSaved: () => void;
}) {
  const t = useT();

  const [form, setForm] = useState(() => ({
    period_start: settlement.period.from ?? "",
    period_end: settlement.period.to ?? "",
    cash: String(settlement.cash_collected),
    fees: String(settlement.fees_charged),
    net: String(settlement.net_amount),
    orders: String(settlement.orders_count),
    reference: settlement.reference ?? "",
    note: settlement.note ?? "",
  }));

  // Eight fields go up together, so a single toast would not say which figure was refused.
  const fields = useFieldErrors({
    only: [
      "period_start",
      "period_end",
      "cash_collected",
      "fees_charged",
      "net_amount",
      "orders_count",
      "reference",
      "note",
    ],
  });

  const save = useMutation({
    mutationFn: () => {
      const input: SettlementInput = {
        period_start: form.period_start,
        period_end: form.period_end,
        // Not offered as a field: the amounts were counted in this currency, and changing it here
        // would relabel them rather than convert them.
        currency: settlement.currency,
        cash_collected: Number(form.cash),
        fees_charged: Number(form.fees),
        net_amount: Number(form.net),
        orders_count: Number(form.orders || 0),
        reference: form.reference.trim() === "" ? null : form.reference.trim(),
        note: form.note.trim() === "" ? null : form.note.trim(),
      };
      return updateSettlement(settlement.uuid, input);
    },
    onSuccess: (response) => {
      toast.success(response.Message ?? t("settlements.updated"));
      onOpenChange(false);
      onSaved();
    },
    onMutate: fields.reset,
    onError: (error) => {
      // "This settlement is no longer a draft" is a 409 about the row, not a field: that one stays
      // a toast, while a refused date or amount goes under its own input.
      // Anything this form does not render still has to be said out loud.
      if (!fields.capture(error)) toast.error(friendlyErrorMessage(error, t));
    },
  });

  const numeric = (value: string) =>
    value.trim() !== "" && Number.isFinite(Number(value));
  const complete =
    form.period_start !== "" &&
    form.period_end !== "" &&
    numeric(form.cash) &&
    numeric(form.fees) &&
    numeric(form.net);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>{t("settlements.editTitle")}</DialogTitle>
          <DialogDescription>{t("settlements.editBody")}</DialogDescription>
        </DialogHeader>

        <div className="grid grid-cols-2 gap-3">
          <div className="space-y-1.5">
            <Label htmlFor="edit-settlement-from">
              {t("settlements.from")}
            </Label>
            <Input
              id="edit-settlement-from"
              type="date"
              value={form.period_start}
              onChange={(event) =>
                setForm({ ...form, period_start: event.target.value })
              }
            />
            {fields.get("period_start") ? (
              <p className="text-xs text-destructive">
                {fields.get("period_start")}
              </p>
            ) : null}
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="edit-settlement-to">{t("settlements.to")}</Label>
            <Input
              id="edit-settlement-to"
              type="date"
              value={form.period_end}
              onChange={(event) =>
                setForm({ ...form, period_end: event.target.value })
              }
            />
            {fields.get("period_end") ? (
              <p className="text-xs text-destructive">
                {fields.get("period_end")}
              </p>
            ) : null}
          </div>
        </div>

        <div className="grid grid-cols-3 gap-2">
          <div className="space-y-1.5">
            <Label htmlFor="edit-settlement-cash">
              {t("settlements.cashCollected")}
            </Label>
            <Input
              id="edit-settlement-cash"
              type="number"
              step="0.01"
              dir="ltr"
              value={form.cash}
              onChange={(event) =>
                setForm({ ...form, cash: event.target.value })
              }
            />
            {fields.get("cash_collected") ? (
              <p className="text-xs text-destructive">
                {fields.get("cash_collected")}
              </p>
            ) : null}
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="edit-settlement-fees">
              {t("settlements.feesCharged")}
            </Label>
            <Input
              id="edit-settlement-fees"
              type="number"
              step="0.01"
              dir="ltr"
              value={form.fees}
              onChange={(event) =>
                setForm({ ...form, fees: event.target.value })
              }
            />
            {fields.get("fees_charged") ? (
              <p className="text-xs text-destructive">
                {fields.get("fees_charged")}
              </p>
            ) : null}
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="edit-settlement-net">
              {t("settlements.netAmount")}
            </Label>
            <Input
              id="edit-settlement-net"
              type="number"
              step="0.01"
              dir="ltr"
              value={form.net}
              onChange={(event) =>
                setForm({ ...form, net: event.target.value })
              }
            />
            {fields.get("net_amount") ? (
              <p className="text-xs text-destructive">
                {fields.get("net_amount")}
              </p>
            ) : null}
          </div>
        </div>
        <p className="text-xs text-muted-foreground">
          {t("settlements.netHint")}
        </p>

        <div className="grid grid-cols-2 gap-3">
          <div className="space-y-1.5">
            <Label htmlFor="edit-settlement-orders">
              {t("settlements.ordersCount")}
            </Label>
            <Input
              id="edit-settlement-orders"
              type="number"
              min={0}
              dir="ltr"
              value={form.orders}
              onChange={(event) =>
                setForm({ ...form, orders: event.target.value })
              }
            />
            {fields.get("orders_count") ? (
              <p className="text-xs text-destructive">
                {fields.get("orders_count")}
              </p>
            ) : null}
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="edit-settlement-reference">
              {t("settlements.reference")}
            </Label>
            <Input
              id="edit-settlement-reference"
              value={form.reference}
              onChange={(event) =>
                setForm({ ...form, reference: event.target.value })
              }
            />
            {fields.get("reference") ? (
              <p className="text-xs text-destructive">
                {fields.get("reference")}
              </p>
            ) : null}
          </div>
        </div>

        <div className="space-y-1.5">
          <Label htmlFor="edit-settlement-note">{t("settlements.note")}</Label>
          <Textarea
            id="edit-settlement-note"
            rows={2}
            value={form.note}
            onChange={(event) => setForm({ ...form, note: event.target.value })}
          />
          {fields.get("note") ? (
            <p className="text-xs text-destructive">{fields.get("note")}</p>
          ) : null}
        </div>

        <DialogFooter>
          <Button variant="ghost" onClick={() => onOpenChange(false)}>
            {t("common.cancel")}
          </Button>
          <Button
            onClick={() => save.mutate()}
            disabled={save.isPending || !complete}
          >
            {save.isPending ? t("common.saving") : t("common.save")}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
