"use client";

import { useMemo, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { Plus } from "lucide-react";
import { accountingApi } from "@/src/modules/accounting/services/accounting-api";
import { useTenantId } from "@/hooks/useTenantId";
import { formatMoney, parseMoneyInput } from "@/lib/utils";
import {
  PageHeader,
  Button,
  Dialog,
  Input,
  DataTable,
  EmptyState,
  LoadingState,
  ErrorState,
  FormField,
  DatePicker,
  JalaliDateText,
  Select,
  Badge,
} from "@/src/shared/ui";

type InvoiceLine = {
  title: string;
  qty: string;
  unit_price: string;
  note?: string;
  item_id?: string;
};

type ReturnLine = InvoiceLine & {
  return_qty: string;
  selected: boolean;
  invoice_line_index: number;
};

type FormValues = {
  number: string;
  doc_date: string;
  source_invoice_id: string;
  description: string;
};

function parseMeta(meta: unknown): {
  lines?: InvoiceLine[];
  source_invoice_id?: string;
  source_invoice_number?: string;
  accounting_voucher?: { voucher_number?: string };
} {
  if (!meta) return {};
  try {
    const raw = typeof meta === "string" ? JSON.parse(meta) : meta;
    return (raw && typeof raw === "object" ? raw : {}) as ReturnType<typeof parseMeta>;
  } catch {
    return {};
  }
}

function lineAmount(qty: string, unitPrice: string): number {
  return Number(parseMoneyInput(qty) || "0") * Number(parseMoneyInput(unitPrice) || "0");
}

export function PurchaseReturnsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const [returnLines, setReturnLines] = useState<ReturnLine[]>([]);

  const returnsQ = useQuery({
    queryKey: ["accounting", tenantId, "ops-docs", "purchase", "return"],
    queryFn: () => accountingApi.ops.listDocuments(tenantId!, "purchase", "return"),
    enabled: !!tenantId,
  });
  const invoicesQ = useQuery({
    queryKey: ["accounting", tenantId, "ops-docs", "purchase", "invoice"],
    queryFn: () => accountingApi.ops.listDocuments(tenantId!, "purchase", "invoice"),
    enabled: !!tenantId,
  });
  const policyQ = useQuery({
    queryKey: ["accounting", tenantId, "posting-policy"],
    queryFn: () => accountingApi.setup.getPostingPolicy(tenantId!),
    enabled: !!tenantId,
  });
  useQuery({
    queryKey: ["accounting", tenantId, "purchase-profiles-ensure"],
    queryFn: () => accountingApi.purchaseInventory.ensureDefaultProfile(tenantId!),
    enabled: !!tenantId,
    staleTime: 60_000,
  });

  const form = useForm<FormValues>({
    defaultValues: {
      number: "",
      doc_date: new Date().toISOString().slice(0, 10),
      source_invoice_id: "",
      description: "",
    },
  });

  const invoiceId = form.watch("source_invoice_id");
  const selectedInvoice = useMemo(
    () => (invoicesQ.data ?? []).find((i) => i.id === invoiceId),
    [invoicesQ.data, invoiceId]
  );

  const returnTotal = useMemo(
    () =>
      returnLines
        .filter((l) => l.selected)
        .reduce((sum, l) => sum + lineAmount(l.return_qty, l.unit_price), 0),
    [returnLines]
  );

  const autoReturn = Boolean(policyQ.data?.auto_post?.purchase_return ?? true);

  const onInvoiceChange = (id: string) => {
    form.setValue("source_invoice_id", id);
    const inv = (invoicesQ.data ?? []).find((i) => i.id === id);
    if (!inv) {
      setReturnLines([]);
      return;
    }
    const meta = parseMeta(inv.meta_json);
    const lines = meta.lines ?? [];
    if (!lines.length) {
      // Invoice without line items: treat whole amount as one returnable row
      setReturnLines([
        {
          title: inv.description || `فاکتور ${inv.number}`,
          qty: "1",
          unit_price: String(inv.amount || "0"),
          return_qty: "1",
          selected: true,
          invoice_line_index: 0,
        },
      ]);
      return;
    }
    setReturnLines(
      lines.map((ln, idx) => ({
        title: ln.title || "کالا",
        qty: ln.qty || "1",
        unit_price: ln.unit_price || "0",
        note: ln.note,
        item_id: ln.item_id,
        return_qty: ln.qty || "1",
        selected: true,
        invoice_line_index: idx,
      }))
    );
  };

  const createM = useMutation({
    mutationFn: async (d: FormValues) => {
      if (!selectedInvoice) throw new Error("فاکتور خرید را انتخاب کنید");
      const selected = returnLines.filter((l) => l.selected && Number(parseMoneyInput(l.return_qty) || "0") > 0);
      if (!selected.length) throw new Error("حداقل یک کالا با تعداد مرجوعی مشخص کنید");

      for (const ln of selected) {
        const maxQty = Number(parseMoneyInput(ln.qty) || "0");
        const retQty = Number(parseMoneyInput(ln.return_qty) || "0");
        if (retQty > maxQty) {
          throw new Error(`تعداد مرجوعی «${ln.title}» بیشتر از فاکتور است`);
        }
      }

      const amount = String(returnTotal);
      if (Number(amount) <= 0) throw new Error("مبلغ مرجوعی باید بزرگ‌تر از صفر باشد");

      const linesPayload = selected.map((l) => ({
        title: l.title,
        qty: parseMoneyInput(l.return_qty) || "0",
        unit_price: parseMoneyInput(l.unit_price) || "0",
        note: l.note,
        item_id: l.item_id,
        invoice_line_index: l.invoice_line_index,
        invoice_qty: l.qty,
      }));

      const doc = await accountingApi.ops.createDocument(tenantId!, {
        module: "purchase",
        doc_type: "return",
        number: d.number?.trim() || undefined,
        doc_date: d.doc_date,
        party_name: selectedInvoice.party_name || undefined,
        party_id: selectedInvoice.party_id || undefined,
        amount,
        description:
          d.description ||
          `مرجوعی از فاکتور ${selectedInvoice.number}` +
            (selectedInvoice.party_name ? ` — ${selectedInvoice.party_name}` : ""),
        status: "draft",
        meta_json: JSON.stringify({
          source_invoice_id: selectedInvoice.id,
          source_invoice_number: selectedInvoice.number,
          party_name: selectedInvoice.party_name,
          party_id: selectedInvoice.party_id,
          lines: linesPayload,
        }),
      });

      if (autoReturn) {
        // Confirm triggers auto GL (Dr AP / Cr inventory) + supplier balance decrease
        const confirmed = await accountingApi.ops.confirmDocument(tenantId!, String(doc.id));
        return confirmed;
      }
      return doc;
    },
    onSuccess: async (res) => {
      const meta =
        res && typeof res === "object" && "meta_json" in res
          ? parseMeta((res as { meta_json?: string | null }).meta_json)
          : {};
      const vn = meta.accounting_voucher?.voucher_number || "";
      toast.success(
        vn
          ? `مرجوعی ثبت شد — سند ${vn} (کاهش بدهی تأمین‌کننده)`
          : "مرجوعی ثبت شد"
      );
      setOpen(false);
      form.reset();
      setReturnLines([]);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "ops-docs", "purchase", "return"] });
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "vouchers"] });
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "suppliers"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  if (!tenantId || returnsQ.isLoading) return <LoadingState />;
  if (returnsQ.error) return <ErrorState message={returnsQ.error.message} onRetry={() => returnsQ.refetch()} />;

  const invoices = (invoicesQ.data ?? []).filter((i) => i.status !== "cancelled");

  return (
    <div>
      <PageHeader
        title="مرجوعی خرید"
        description="فاکتور خرید را انتخاب کنید، کالاهای مرجوعی را مشخص کنید — سند اتومات بدهی تأمین‌کننده را کاهش می‌دهد (Dr حساب پرداختنی / Cr موجودی)."
        actions={
          <Button type="button" onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            مرجوعی جدید
          </Button>
        }
      />

      <DataTable
        columns={[
          { key: "number", header: "شماره مرجوعی" },
          {
            key: "doc_date",
            header: "تاریخ",
            render: (r) => <JalaliDateText value={String(r.doc_date ?? "")} />,
          },
          {
            key: "invoice",
            header: "فاکتور مبدأ",
            render: (r) => parseMeta(r.meta_json).source_invoice_number || "—",
          },
          { key: "party_name", header: "تأمین‌کننده" },
          {
            key: "items",
            header: "کالاها",
            render: (r) => {
              const lines = parseMeta(r.meta_json).lines ?? [];
              if (!lines.length) return "—";
              return lines.map((l) => `${l.title}×${l.qty}`).join("، ");
            },
          },
          {
            key: "amount",
            header: "مبلغ",
            render: (r) => formatMoney(String(r.amount ?? "0")),
          },
          {
            key: "status",
            header: "وضعیت",
            render: (r) => (
              <Badge tone={r.status === "posted" || r.status === "confirmed" ? "success" : "default"}>
                {String(r.status)}
              </Badge>
            ),
          },
          {
            key: "voucher",
            header: "سند GL",
            render: (r) => parseMeta(r.meta_json).accounting_voucher?.voucher_number || "—",
          },
        ]}
        rows={(returnsQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="مرجوعی ثبت نشده" description="از فاکتور خرید، مرجوعی ثبت کنید." />}
      />

      <Dialog open={open} onClose={() => setOpen(false)} title="مرجوعی خرید از فاکتور" size="xl">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((d) => createM.mutate(d))}>
          <FormField label="فاکتور خرید مبدأ" hint="مرجوعی باید به یک فاکتور خرید وصل باشد">
            <Select
              value={invoiceId}
              onChange={(e) => onInvoiceChange(e.target.value)}
              required
            >
              <option value="">انتخاب فاکتور…</option>
              {invoices.map((inv) => (
                <option key={inv.id} value={inv.id}>
                  {inv.number} — {inv.party_name || "بدون تأمین‌کننده"} — {formatMoney(String(inv.amount))}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="تاریخ مرجوعی">
            <Controller
              control={form.control}
              name="doc_date"
              render={({ field }) => (
                <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
              )}
            />
          </FormField>

          {selectedInvoice ? (
            <div className="sm:col-span-2 rounded-xl border border-[var(--border)] bg-[var(--surface-2)] p-3 text-sm">
              <div>
                تأمین‌کننده: <strong>{selectedInvoice.party_name || "—"}</strong>
              </div>
              <div className="mt-1 text-[var(--muted)]">
                فاکتور {selectedInvoice.number} — مبلغ فاکتور {formatMoney(String(selectedInvoice.amount))}
              </div>
            </div>
          ) : null}

          {returnLines.length > 0 ? (
            <div className="sm:col-span-2 overflow-x-auto">
              <table className="w-full min-w-[520px] text-sm">
                <thead>
                  <tr className="border-b border-[var(--border)] text-right text-[var(--muted)]">
                    <th className="p-2 font-medium">انتخاب</th>
                    <th className="p-2 font-medium">کالا (از فاکتور)</th>
                    <th className="p-2 font-medium">تعداد فاکتور</th>
                    <th className="p-2 font-medium">تعداد مرجوعی</th>
                    <th className="p-2 font-medium">فی</th>
                    <th className="p-2 font-medium">جمع</th>
                  </tr>
                </thead>
                <tbody>
                  {returnLines.map((ln, idx) => (
                    <tr key={idx} className="border-b border-[var(--border)]">
                      <td className="p-2">
                        <input
                          type="checkbox"
                          checked={ln.selected}
                          onChange={(e) => {
                            const next = [...returnLines];
                            next[idx] = { ...ln, selected: e.target.checked };
                            setReturnLines(next);
                          }}
                        />
                      </td>
                      <td className="p-2">{ln.title}</td>
                      <td className="p-2" dir="ltr">
                        {ln.qty}
                      </td>
                      <td className="p-2">
                        <Input
                          value={ln.return_qty}
                          disabled={!ln.selected}
                          onChange={(e) => {
                            const next = [...returnLines];
                            next[idx] = { ...ln, return_qty: e.target.value };
                            setReturnLines(next);
                          }}
                        />
                      </td>
                      <td className="p-2" dir="ltr">
                        {formatMoney(parseMoneyInput(ln.unit_price) || "0")}
                      </td>
                      <td className="p-2" dir="ltr">
                        {ln.selected
                          ? formatMoney(String(lineAmount(ln.return_qty, ln.unit_price)))
                          : "—"}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          ) : null}

          <FormField label="جمع مرجوعی">
            <Input value={formatMoney(String(returnTotal))} readOnly dir="ltr" />
          </FormField>
          <FormField label="شماره مرجوعی (اختیاری)">
            <Input {...form.register("number")} placeholder="خالی = خودکار" />
          </FormField>
          <div className="sm:col-span-2">
            <FormField label="توضیح">
              <Input {...form.register("description")} placeholder="اختیاری" />
            </FormField>
          </div>

          <div className="sm:col-span-2 flex justify-end gap-2">
            <Button type="button" variant="secondary" onClick={() => setOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" loading={createM.isPending} disabled={!invoiceId || returnTotal <= 0}>
              ثبت مرجوعی{autoReturn ? " + سند اتومات" : ""}
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}
