"use client";

import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { Eye, Pencil, 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,
  Badge,
  FormField,
  MoneyInput,
  DatePicker,
  JalaliDateText,
  ConfirmDialog,
  Tabs,
  Select,
} from "@/src/shared/ui";
import { PartyCombobox } from "@/src/modules/accounting/components/EntityCombobox";

const schema = z.object({
  number: z.string().min(1, "شماره الزامی است"),
  doc_date: z.string().min(1, "تاریخ الزامی است"),
  party_name: z.string().optional(),
  party_id: z.string().optional(),
  amount: z.string().min(1, "مبلغ الزامی است"),
  description: z.string().optional(),
});

type FormValues = z.infer<typeof schema>;

export function BusinessDocsPage({
  title,
  description,
  module,
  docType,
}: {
  title: string;
  description?: string;
  module: string;
  docType: string;
}) {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const [confirmId, setConfirmId] = useState<string | null>(null);
  const [detailRow, setDetailRow] = useState<Record<string, unknown> | null>(null);
  const [editRow, setEditRow] = useState<Record<string, unknown> | null>(null);

  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "ops-docs", module, docType],
    queryFn: () => accountingApi.ops.listDocuments(tenantId!, module, docType),
    enabled: !!tenantId,
  });

  const form = useForm<FormValues>({
    resolver: zodResolver(schema),
    defaultValues: {
      number: "",
      doc_date: new Date().toISOString().slice(0, 10),
      party_name: "",
      party_id: "",
      amount: "0",
      description: "",
    },
  });
  const editForm = useForm<FormValues>({
    resolver: zodResolver(schema),
    defaultValues: {
      number: "",
      doc_date: "",
      party_name: "",
      party_id: "",
      amount: "0",
      description: "",
    },
  });

  const createM = useMutation({
    mutationFn: (d: FormValues) =>
      accountingApi.ops.createDocument(tenantId!, {
        module,
        doc_type: docType,
        number: d.number,
        doc_date: d.doc_date,
        party_name: d.party_name || undefined,
        party_id: d.party_id || undefined,
        amount: parseMoneyInput(d.amount) || "0",
        description: d.description || undefined,
        status: "draft",
      }),
    onSuccess: async () => {
      toast.success("ثبت شد");
      setOpen(false);
      form.reset({
        number: "",
        doc_date: new Date().toISOString().slice(0, 10),
        party_name: "",
        party_id: "",
        amount: "0",
        description: "",
      });
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "ops-docs", module, docType] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const confirmM = useMutation({
    mutationFn: (id: string) => accountingApi.ops.confirmDocument(tenantId!, id),
    onSuccess: async () => {
      toast.success("تأیید شد");
      setConfirmId(null);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "ops-docs", module, docType] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const openEdit = (row: Record<string, unknown>) => {
    setEditRow(row);
    editForm.reset({
      number: String(row.number ?? ""),
      doc_date: String(row.doc_date ?? ""),
      party_name: String(row.party_name ?? ""),
      party_id: String(row.party_id ?? ""),
      amount: String(row.amount ?? "0"),
      description: String(row.description ?? ""),
    });
  };

  const updateM = useMutation({
    mutationFn: (d: FormValues) =>
      accountingApi.ops.updateDocument(tenantId!, String(editRow!.id), {
        doc_date: d.doc_date,
        party_name: d.party_name || undefined,
        party_id: d.party_id || undefined,
        amount: parseMoneyInput(d.amount) || "0",
        description: d.description || undefined,
      }),
    onSuccess: async () => {
      toast.success("ویرایش ذخیره شد");
      setEditRow(null);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "ops-docs", module, docType] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

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

  return (
    <div>
      <PageHeader
        title={title}
        description={description || "لیست و ثبت — متصل به API واقعی حسابداری."}
        actions={
          <Button type="button" onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            {title.includes("فاکتور") || title.includes("سند") || title.includes("چک")
              ? `${title} جدید`
              : `ثبت ${title}`}
          </Button>
        }
      />

      <DataTable
        columns={[
          { key: "number", header: "شماره" },
          {
            key: "doc_date",
            header: "تاریخ",
            render: (r) => <JalaliDateText value={String(r.doc_date ?? "")} />,
          },
          { key: "party_name", header: "طرف حساب" },
          {
            key: "amount",
            header: "مبلغ",
            render: (r) => formatMoney(String(r.amount ?? "0")),
          },
          {
            key: "status",
            header: "وضعیت",
            render: (r) => (
              <Badge tone={r.status === "confirmed" ? "success" : "default"}>{String(r.status)}</Badge>
            ),
          },
          {
            key: "id",
            header: "عملیات",
            render: (r) => (
              <div className="flex flex-wrap gap-2">
                <Button type="button" size="sm" variant="ghost" onClick={() => setDetailRow(r)}>
                  <Eye className="h-4 w-4" />
                  جزئیات
                </Button>
                {r.status === "draft" ? (
                  <>
                    <Button type="button" size="sm" variant="outline" onClick={() => openEdit(r)}>
                      <Pencil className="h-4 w-4" />
                      ویرایش
                    </Button>
                    <Button type="button" size="sm" variant="outline" onClick={() => setConfirmId(String(r.id))}>
                      تأیید
                    </Button>
                  </>
                ) : null}
              </div>
            ),
          },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={
          <EmptyState
            title="موردی ثبت نشده"
            description="با دکمه ثبت جدید در بالای صفحه شروع کنید."
            action={
              <Button type="button" onClick={() => setOpen(true)}>
                <Plus className="h-4 w-4" />
                ثبت {title}
              </Button>
            }
          />
        }
      />

      <Dialog open={open} onClose={() => setOpen(false)} title={`ثبت ${title}`} size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((d) => createM.mutate(d))}>
          <FormField label="شماره" error={form.formState.errors.number?.message}>
            <Input {...form.register("number")} />
          </FormField>
          <FormField label="تاریخ" error={form.formState.errors.doc_date?.message}>
            <Controller
              control={form.control}
              name="doc_date"
              render={({ field }) => (
                <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
              )}
            />
          </FormField>
          <FormField label="طرف حساب">
            <PartyCombobox
              module={module}
              valueName={form.watch("party_name") || undefined}
              onChange={(party) => {
                form.setValue("party_name", party?.name || "");
                form.setValue("party_id", party?.id || "");
              }}
            />
          </FormField>
          <FormField label="مبلغ" error={form.formState.errors.amount?.message}>
            <MoneyInput {...form.register("amount")} />
          </FormField>
          <div className="sm:col-span-2">
            <FormField label="توضیح">
              <Input {...form.register("description")} />
            </FormField>
          </div>
          <div className="flex justify-end gap-2 sm:col-span-2">
            <Button type="button" variant="outline" onClick={() => setOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createM.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>

      <Dialog open={!!editRow} onClose={() => setEditRow(null)} title={`ویرایش ${title}`} size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={editForm.handleSubmit((d) => updateM.mutate(d))}>
          <FormField label="شماره">
            <Input {...editForm.register("number")} readOnly />
          </FormField>
          <FormField label="تاریخ" error={editForm.formState.errors.doc_date?.message}>
            <Controller
              control={editForm.control}
              name="doc_date"
              render={({ field }) => (
                <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
              )}
            />
          </FormField>
          <FormField label="طرف حساب">
            <PartyCombobox
              module={module}
              valueName={editForm.watch("party_name") || undefined}
              onChange={(party) => {
                editForm.setValue("party_name", party?.name || "");
                editForm.setValue("party_id", party?.id || "");
              }}
            />
          </FormField>
          <FormField label="مبلغ" error={editForm.formState.errors.amount?.message}>
            <MoneyInput {...editForm.register("amount")} />
          </FormField>
          <div className="sm:col-span-2">
            <FormField label="توضیح">
              <Input {...editForm.register("description")} />
            </FormField>
          </div>
          <div className="flex justify-end gap-2 sm:col-span-2">
            <Button type="button" variant="outline" onClick={() => setEditRow(null)}>انصراف</Button>
            <Button type="submit" disabled={updateM.isPending}>ذخیره تغییرات</Button>
          </div>
        </form>
      </Dialog>

      <Dialog open={!!detailRow} onClose={() => setDetailRow(null)} title={`جزئیات ${title}`}>
        {detailRow ? (
          <dl className="grid gap-4 text-sm sm:grid-cols-2">
            <div><dt className="text-[var(--muted)]">شماره</dt><dd className="mt-1 text-secondary">{String(detailRow.number ?? "—")}</dd></div>
            <div><dt className="text-[var(--muted)]">تاریخ</dt><dd className="mt-1 text-secondary"><JalaliDateText value={String(detailRow.doc_date ?? "")} /></dd></div>
            <div><dt className="text-[var(--muted)]">طرف حساب</dt><dd className="mt-1 text-secondary">{String(detailRow.party_name ?? "—")}</dd></div>
            <div><dt className="text-[var(--muted)]">مبلغ</dt><dd className="mt-1 text-secondary">{formatMoney(String(detailRow.amount ?? "0"))}</dd></div>
            <div><dt className="text-[var(--muted)]">وضعیت</dt><dd className="mt-1"><Badge>{String(detailRow.status ?? "—")}</Badge></dd></div>
            <div className="sm:col-span-2"><dt className="text-[var(--muted)]">توضیح</dt><dd className="mt-1 text-secondary">{String(detailRow.description ?? "—")}</dd></div>
          </dl>
        ) : null}
      </Dialog>

      <ConfirmDialog
        open={!!confirmId}
        onClose={() => setConfirmId(null)}
        onConfirm={() => confirmId && confirmM.mutate(confirmId)}
        title="تأیید سند؟"
        description="پس از تأیید، وضعیت به confirmed تغییر می‌کند."
        confirmLabel="تأیید"
        loading={confirmM.isPending}
      />
    </div>
  );
}

export function BlockedModulePage({ title }: { title: string }) {
  return (
    <div>
      <PageHeader title={title} description="این بخش تا Active شدن AI Provider مسدود است." />
      <EmptyState
        title="مسدود"
        description="طبق تصمیم پروژه، ماژول هوش مصنوعی حسابداری تا فعال‌سازی provider نمایش داده نمی‌شود."
      />
    </div>
  );
}

export function InventoryItemsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const form = useForm({
    defaultValues: { code: "", name: "", unit: "عدد", quantity_on_hand: "0", unit_cost: "0" },
  });

  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "ops-items"],
    queryFn: () => accountingApi.ops.listItems(tenantId!),
    enabled: !!tenantId,
  });

  const createM = useMutation({
    mutationFn: (d: { code: string; name: string; unit: string; quantity_on_hand: string; unit_cost: string }) =>
      accountingApi.ops.createItem(tenantId!, d),
    onSuccess: async () => {
      toast.success("کالا ثبت شد");
      setOpen(false);
      form.reset();
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "ops-items"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

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

  return (
    <div>
      <PageHeader
        title="کارت کالا / خدمت"
        description="فهرست اقلام انبار — CRUD واقعی."
        actions={
          <Button type="button" onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            کالای جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "code", header: "کد" },
          { key: "name", header: "نام" },
          { key: "unit", header: "واحد" },
          {
            key: "quantity_on_hand",
            header: "موجودی",
            render: (r) => String(r.quantity_on_hand ?? "0"),
          },
          {
            key: "unit_cost",
            header: "بهای واحد",
            render: (r) => formatMoney(String(r.unit_cost ?? "0")),
          },
          {
            key: "is_active",
            header: "وضعیت",
            render: (r) => <Badge tone={r.is_active ? "success" : "default"}>{r.is_active ? "فعال" : "غیرفعال"}</Badge>,
          },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="کالایی ثبت نشده" />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="ثبت کالا">
        <form
          className="grid gap-3 sm:grid-cols-2"
          onSubmit={form.handleSubmit((d) => createM.mutate(d))}
        >
          <FormField label="کد">
            <Input {...form.register("code", { required: true })} />
          </FormField>
          <FormField label="نام">
            <Input {...form.register("name", { required: true })} />
          </FormField>
          <FormField label="واحد">
            <Input {...form.register("unit")} />
          </FormField>
          <FormField label="موجودی">
            <Input {...form.register("quantity_on_hand")} />
          </FormField>
          <FormField label="بهای واحد">
            <MoneyInput {...form.register("unit_cost")} />
          </FormField>
          <div className="flex justify-end gap-2 sm:col-span-2">
            <Button type="button" variant="outline" onClick={() => setOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createM.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}

export function WarehousesPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const form = useForm({ defaultValues: { code: "", name: "" } });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "ops-warehouses"],
    queryFn: () => accountingApi.ops.listWarehouses(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (d: { code: string; name: string }) => accountingApi.ops.createWarehouse(tenantId!, d),
    onSuccess: async () => {
      toast.success("انبار ثبت شد");
      setOpen(false);
      form.reset();
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "ops-warehouses"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

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

  return (
    <div>
      <PageHeader
        title="تنظیمات انبار"
        description="تعریف انبارها."
        actions={
          <Button type="button" onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            انبار جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "code", header: "کد" },
          { key: "name", header: "نام" },
          {
            key: "is_active",
            header: "وضعیت",
            render: (r) => <Badge tone={r.is_active ? "success" : "default"}>{r.is_active ? "فعال" : "غیرفعال"}</Badge>,
          },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="انباری ثبت نشده" />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="ثبت انبار">
        <form className="grid gap-3" onSubmit={form.handleSubmit((d) => createM.mutate(d))}>
          <FormField label="کد">
            <Input {...form.register("code", { required: true })} />
          </FormField>
          <FormField label="نام">
            <Input {...form.register("name", { required: true })} />
          </FormField>
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createM.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}

export function ChequesPage({
  defaultIncoming,
  initialOpen = false,
}: {
  defaultIncoming?: boolean;
  initialOpen?: boolean;
}) {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [tab, setTab] = useState<"all" | "in" | "out" | "bounced">("all");
  const [open, setOpen] = useState(initialOpen);
  const form = useForm({
    defaultValues: {
      cheque_number: "",
      amount: "0",
      issue_date: new Date().toISOString().slice(0, 10),
      due_date: "",
      is_incoming: defaultIncoming !== false,
      payee: "",
    },
  });

  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "cheques"],
    queryFn: () => accountingApi.treasury.listCheques(tenantId!),
    enabled: !!tenantId,
  });

  const createM = useMutation({
    mutationFn: (d: {
      cheque_number: string;
      amount: string;
      issue_date: string;
      due_date?: string;
      is_incoming: boolean;
      payee?: string;
    }) =>
      accountingApi.treasury.createCheque(tenantId!, {
        ...d,
        due_date: d.due_date || undefined,
        status: d.is_incoming ? "received" : "issued",
      }),
    onSuccess: async () => {
      toast.success("چک ثبت شد");
      setOpen(false);
      form.reset({
        cheque_number: "",
        amount: "0",
        issue_date: new Date().toISOString().slice(0, 10),
        due_date: "",
        is_incoming: true,
        payee: "",
      });
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "cheques"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

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

  const rows = (listQ.data ?? []).filter((c) => {
    if (tab === "in") return c.is_incoming;
    if (tab === "out") return !c.is_incoming;
    if (tab === "bounced") return c.status === "bounced";
    return true;
  });

  return (
    <div>
      <PageHeader
        title="چک‌ها"
        description="لیست و ثبت چک‌های دریافتی و پرداختی."
        actions={
          <Button type="button" onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            ثبت چک
          </Button>
        }
      />
      <Tabs
        value={tab}
        onChange={(v) => setTab(v as typeof tab)}
        items={[
          { id: "all", label: "همه" },
          { id: "in", label: "دریافتی" },
          { id: "out", label: "پرداختی" },
          { id: "bounced", label: "برگشتی" },
        ]}
      />
      <div className="mt-4">
        <DataTable
          columns={[
            { key: "cheque_number", header: "شماره چک" },
            {
              key: "due_date",
              header: "سررسید",
              render: (r) => (r.due_date ? <JalaliDateText value={String(r.due_date)} /> : "—"),
            },
            {
              key: "issue_date",
              header: "تاریخ",
              render: (r) => <JalaliDateText value={String(r.issue_date)} />,
            },
            { key: "payee", header: "ذینفع" },
            {
              key: "status",
              header: "وضعیت",
              render: (r) => <Badge>{String(r.status)}</Badge>,
            },
            {
              key: "amount",
              header: "مبلغ",
              render: (r) => formatMoney(String(r.amount)),
            },
          ]}
          rows={rows as unknown as Record<string, unknown>[]}
          empty={<EmptyState title="چکی ثبت نشده" />}
        />
      </div>
      <Dialog open={open} onClose={() => setOpen(false)} title="ثبت چک جدید" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((d) => createM.mutate(d))}>
          <div className="sm:col-span-2">
            <FormField label="نوع">
              <Select
                value={form.watch("is_incoming") ? "in" : "out"}
                onChange={(e) => form.setValue("is_incoming", e.target.value === "in")}
              >
                <option value="in">دریافتی</option>
                <option value="out">پرداختی</option>
              </Select>
            </FormField>
          </div>
          <FormField label="شماره چک">
            <Input {...form.register("cheque_number", { required: true })} />
          </FormField>
          <FormField label="مبلغ">
            <MoneyInput {...form.register("amount", { required: true })} />
          </FormField>
          <FormField label="تاریخ صدور">
            <Controller
              control={form.control}
              name="issue_date"
              render={({ field }) => (
                <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
              )}
            />
          </FormField>
          <FormField label="سررسید">
            <Controller
              control={form.control}
              name="due_date"
              render={({ field }) => (
                <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
              )}
            />
          </FormField>
          <FormField label="ذینفع / طرف حساب">
            <Input {...form.register("payee")} />
          </FormField>
          <div className="flex justify-end gap-2 sm:col-span-2">
            <Button type="button" variant="outline" onClick={() => setOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createM.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}

export function ReceiptsPaymentsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [mode, setMode] = useState<"receipt" | "payment">("receipt");
  const [open, setOpen] = useState(false);
  const form = useForm({
    defaultValues: {
      number: "",
      date: new Date().toISOString().slice(0, 10),
      amount: "0",
      payment_method: "cash",
      cash_box_id: "",
      bank_account_id: "",
      counter_account_id: "",
      description: "",
    },
  });

  const receiptsQ = useQuery({
    queryKey: ["accounting", tenantId, "receipts"],
    queryFn: () => accountingApi.treasury.listReceipts(tenantId!),
    enabled: !!tenantId,
  });
  const paymentsQ = useQuery({
    queryKey: ["accounting", tenantId, "payments"],
    queryFn: () => accountingApi.treasury.listPayments(tenantId!),
    enabled: !!tenantId,
  });
  const cashBoxesQ = useQuery({
    queryKey: ["accounting", tenantId, "cash-boxes"],
    queryFn: () => accountingApi.treasury.listCashBoxes(tenantId!),
    enabled: !!tenantId,
  });
  const bankAccountsQ = useQuery({
    queryKey: ["accounting", tenantId, "bank-accounts"],
    queryFn: () => accountingApi.treasury.listBankAccounts(tenantId!),
    enabled: !!tenantId,
  });
  const accountsQ = useQuery({
    queryKey: ["accounting", tenantId, "accounts"],
    queryFn: () => accountingApi.accounts.list(tenantId!),
    enabled: !!tenantId,
  });
  const policyQ = useQuery({
    queryKey: ["accounting", tenantId, "posting-policy"],
    queryFn: () => accountingApi.setup.getPostingPolicy(tenantId!),
    enabled: !!tenantId,
  });

  const autoPost =
    mode === "receipt"
      ? Boolean(policyQ.data?.auto_post?.treasury_receipt ?? true)
      : Boolean(policyQ.data?.auto_post?.treasury_payment ?? true);

  const createM = useMutation({
    mutationFn: async (d: {
      number: string;
      date: string;
      amount: string;
      payment_method: string;
      cash_box_id?: string;
      bank_account_id?: string;
      counter_account_id?: string;
      description?: string;
    }) => {
      if (autoPost && !d.counter_account_id) {
        throw new Error("حساب مقابل برای ثبت خودکار سند حسابداری الزامی است");
      }
      const counter = d.counter_account_id || undefined;
      if (mode === "receipt") {
        return accountingApi.treasury.createReceipt(tenantId!, {
          receipt_number: d.number,
          receipt_date: d.date,
          amount: d.amount,
          payment_method: d.payment_method,
          cash_box_id: d.payment_method === "cash" ? d.cash_box_id || undefined : undefined,
          bank_account_id: d.payment_method === "bank" ? d.bank_account_id || undefined : undefined,
          counter_account_id: counter,
          description: d.description,
        });
      }
      return accountingApi.treasury.createPayment(tenantId!, {
        payment_number: d.number,
        payment_date: d.date,
        amount: d.amount,
        payment_method: d.payment_method,
        cash_box_id: d.payment_method === "cash" ? d.cash_box_id || undefined : undefined,
        bank_account_id: d.payment_method === "bank" ? d.bank_account_id || undefined : undefined,
        counter_account_id: counter,
        description: d.description,
      });
    },
    onSuccess: async (res) => {
      const vn =
        res && typeof res === "object" && "voucher_number" in res
          ? String((res as { voucher_number?: string | null }).voucher_number || "")
          : "";
      toast.success(vn ? `ثبت شد — سند حسابداری ${vn}` : "ثبت شد");
      setOpen(false);
      form.reset();
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "receipts"] });
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "payments"] });
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "vouchers"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

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

  const postable = (accountsQ.data ?? []).filter((a) => a.is_postable);
  const rows =
    mode === "receipt"
      ? (receiptsQ.data ?? []).map((r) => ({
          id: r.id,
          number: r.receipt_number,
          date: r.receipt_date,
          amount: r.amount,
          payment_method: r.payment_method,
          description: r.description,
          voucher_id: r.voucher_id,
        }))
      : (paymentsQ.data ?? []).map((p) => ({
          id: p.id,
          number: p.payment_number,
          date: p.payment_date,
          amount: p.amount,
          payment_method: p.payment_method,
          description: p.description,
          voucher_id: p.voucher_id,
        }));

  return (
    <div>
      <PageHeader
        title="دریافت و پرداخت"
        description={
          autoPost
            ? "ثبت دریافت/پرداخت با صدور خودکار سند حسابداری (قابل تنظیم در اسناد اتوماتیک)."
            : "ثبت دریافت/پرداخت خزانه — ثبت خودکار دفتر کل فعلاً خاموش است."
        }
        actions={
          <Button type="button" onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            ثبت جدید
          </Button>
        }
      />
      <Tabs
        value={mode}
        onChange={(v) => setMode(v as typeof mode)}
        items={[
          { id: "receipt", label: "دریافت‌ها" },
          { id: "payment", label: "پرداخت‌ها" },
        ]}
      />
      <div className="mt-4">
        <DataTable
          columns={[
            { key: "number", header: "شماره" },
            {
              key: "date",
              header: "تاریخ",
              render: (r) => <JalaliDateText value={String(r.date)} />,
            },
            { key: "payment_method", header: "روش" },
            {
              key: "amount",
              header: "مبلغ",
              render: (r) => formatMoney(String(r.amount)),
            },
            {
              key: "voucher_id",
              header: "سند GL",
              render: (r) => (r.voucher_id ? <Badge tone="success">ثبت‌شده</Badge> : "—"),
            },
            { key: "description", header: "توضیح" },
          ]}
          rows={rows as unknown as Record<string, unknown>[]}
          empty={<EmptyState title="موردی نیست" />}
        />
      </div>
      <Dialog open={open} onClose={() => setOpen(false)} title={mode === "receipt" ? "ثبت دریافت" : "ثبت پرداخت"}>
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((d) => createM.mutate(d))}>
          <div className="sm:col-span-2">
            <FormField label="نوع عملیات">
              <Select value={mode} onChange={(e) => setMode(e.target.value as typeof mode)}>
                <option value="receipt">دریافت</option>
                <option value="payment">پرداخت</option>
              </Select>
            </FormField>
          </div>
          <FormField label="شماره">
            <Input {...form.register("number", { required: true })} />
          </FormField>
          <FormField label="مبلغ">
            <MoneyInput {...form.register("amount", { required: true })} />
          </FormField>
          <FormField label="تاریخ">
            <Controller
              control={form.control}
              name="date"
              render={({ field }) => (
                <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
              )}
            />
          </FormField>
          <FormField label="روش">
            <Select
              value={form.watch("payment_method")}
              onChange={(e) => form.setValue("payment_method", e.target.value)}
            >
              <option value="cash">نقد</option>
              <option value="bank">حواله بانکی</option>
              <option value="cheque">چک</option>
            </Select>
          </FormField>
          <FormField label="صندوق">
            <Select {...form.register("cash_box_id")} disabled={form.watch("payment_method") !== "cash"}>
              <option value="">انتخاب صندوق…</option>
              {(cashBoxesQ.data ?? []).map((cashBox) => (
                <option key={cashBox.id} value={cashBox.id}>
                  {cashBox.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="حساب بانکی">
            <Select {...form.register("bank_account_id")} disabled={form.watch("payment_method") !== "bank"}>
              <option value="">انتخاب حساب…</option>
              {(bankAccountsQ.data ?? []).map((account) => (
                <option key={account.id} value={account.id}>
                  {account.account_number}
                </option>
              ))}
            </Select>
          </FormField>
          <div className="sm:col-span-2">
            <FormField label={mode === "receipt" ? "حساب مقابل (بستانکار)" : "حساب مقابل (بدهکار)"}>
              <Select {...form.register("counter_account_id", { required: autoPost })}>
                <option value="">انتخاب حساب…</option>
                {postable.map((a) => (
                  <option key={a.id} value={a.id}>
                    {a.code} — {a.name}
                  </option>
                ))}
              </Select>
            </FormField>
            {autoPost ? (
              <p className="mt-1 text-xs text-[var(--muted)]">
                ثبت خودکار سند دفتر کل فعال است — حساب صندوق/بانک از تنظیمات صندوق/حساب بانکی گرفته می‌شود.
              </p>
            ) : null}
          </div>
          <div className="sm:col-span-2">
            <FormField label="توضیح">
              <Input {...form.register("description")} />
            </FormField>
          </div>
          <div className="flex justify-end gap-2 sm:col-span-2">
            <Button type="button" variant="outline" onClick={() => setOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createM.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}

export function TransfersPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const cashBoxesQ = useQuery({
    queryKey: ["accounting", tenantId, "cash-boxes"],
    queryFn: () => accountingApi.treasury.listCashBoxes(tenantId!),
    enabled: !!tenantId,
  });
  const bankAccountsQ = useQuery({
    queryKey: ["accounting", tenantId, "bank-accounts"],
    queryFn: () => accountingApi.treasury.listBankAccounts(tenantId!),
    enabled: !!tenantId,
  });
  const accountsQ = useQuery({
    queryKey: ["accounting", tenantId, "accounts"],
    queryFn: () => accountingApi.accounts.list(tenantId!),
    enabled: !!tenantId,
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "transfers"],
    queryFn: () => accountingApi.treasury.listTransfers(tenantId!),
    enabled: !!tenantId,
  });
  const form = useForm({
    defaultValues: {
      transfer_date: new Date().toISOString().slice(0, 10),
      amount: "0",
      from_key: "",
      to_key: "",
      description: "",
    },
  });

  const createM = useMutation({
    mutationFn: (d: {
      transfer_date: string;
      amount: string;
      from_key: string;
      to_key: string;
      description?: string;
    }) => {
      const [from_type, from_id] = d.from_key.split(":");
      const [to_type, to_id] = d.to_key.split(":");
      if (!from_type || !from_id || !to_type || !to_id) {
        throw new Error("حساب مبدأ و مقصد را انتخاب کنید");
      }
      if (d.from_key === d.to_key) {
        throw new Error("مبدأ و مقصد نباید یکسان باشند");
      }
      return accountingApi.treasury.createTransfer(tenantId!, {
        transfer_date: d.transfer_date,
        amount: d.amount,
        from_type,
        from_id,
        to_type,
        to_id,
        description: d.description,
      });
    },
    onSuccess: async (res) => {
      const vn =
        res && typeof res === "object" && "voucher_number" in res
          ? String((res as { voucher_number?: string | null }).voucher_number || "")
          : "";
      toast.success(vn ? `انتقال ثبت و سند ${vn} صادر شد` : "انتقال ثبت شد");
      setOpen(false);
      form.reset();
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "transfers"] });
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "vouchers"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

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

  const labelMap = new Map<string, string>();
  const accountOptions = [
    ...(cashBoxesQ.data ?? []).map((c) => {
      const value = `cash:${c.id}`;
      const label = `صندوق: ${c.name}`;
      labelMap.set(value, label);
      return { value, label };
    }),
    ...(bankAccountsQ.data ?? []).map((b) => {
      const value = `bank:${b.id}`;
      const label = `بانک: ${b.account_number}`;
      labelMap.set(value, label);
      return { value, label };
    }),
    ...(accountsQ.data ?? [])
      .filter((a) => a.is_postable)
      .map((a) => {
        const value = `account:${a.id}`;
        const label = `حساب: ${a.code} — ${a.name}`;
        labelMap.set(value, label);
        return { value, label };
      }),
  ];

  const sideLabel = (type: unknown, id: unknown) =>
    labelMap.get(`${String(type)}:${String(id)}`) || `${String(type)}`;

  return (
    <div>
      <PageHeader
        title="انتقال بین حساب‌ها"
        description="از صندوق، بانک یا هر حساب دفتر کل به هر حساب دیگر — سند اتومات: بدهکار مقصد / بستانکار مبدأ."
        actions={
          <Button type="button" onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            انتقال جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          {
            key: "transfer_date",
            header: "تاریخ",
            render: (r) => <JalaliDateText value={String(r.transfer_date)} />,
          },
          {
            key: "amount",
            header: "مبلغ",
            render: (r) => formatMoney(String(r.amount)),
          },
          {
            key: "from_id",
            header: "از",
            render: (r) => sideLabel(r.from_type, r.from_id),
          },
          {
            key: "to_id",
            header: "به",
            render: (r) => sideLabel(r.to_type, r.to_id),
          },
          {
            key: "voucher_id",
            header: "سند GL",
            render: (r) => (r.voucher_id ? <Badge tone="success">صادر شد</Badge> : "—"),
          },
          { key: "description", header: "توضیح" },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="انتقالی ثبت نشده" />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="انتقال بین حساب‌ها">
        <form className="grid gap-3" onSubmit={form.handleSubmit((d) => createM.mutate(d))}>
          <FormField label="تاریخ">
            <Controller
              control={form.control}
              name="transfer_date"
              render={({ field }) => (
                <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
              )}
            />
          </FormField>
          <FormField label="مبلغ">
            <MoneyInput {...form.register("amount", { required: true })} />
          </FormField>
          <FormField label="از حساب (بستانکار می‌شود)" hint="مثال: بانک ملت، صندوق، اشخاص">
            <Select
              value={form.watch("from_key")}
              onChange={(e) => form.setValue("from_key", e.target.value)}
            >
              <option value="">انتخاب…</option>
              {accountOptions.map((o) => (
                <option key={o.value} value={o.value}>
                  {o.label}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="به حساب (بدهکار می‌شود)" hint="مثال: اشخاص، هزینه، صندوق دیگر">
            <Select
              value={form.watch("to_key")}
              onChange={(e) => form.setValue("to_key", e.target.value)}
            >
              <option value="">انتخاب…</option>
              {accountOptions.map((o) => (
                <option key={o.value} value={o.value}>
                  {o.label}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="توضیح">
            <Input {...form.register("description")} />
          </FormField>
          <p className="text-xs text-[var(--muted)]">
            با ذخیره، سند حسابداری خودکار ساخته می‌شود — نیازی به ثبت دستی سند نیست.
          </p>
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createM.isPending}>
              ذخیره و صدور سند
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}

export function ReconciliationPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const banksQ = useQuery({
    queryKey: ["accounting", tenantId, "bank-accounts"],
    queryFn: () => accountingApi.treasury.listBankAccounts(tenantId!),
    enabled: !!tenantId,
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "reconciliations"],
    queryFn: () => accountingApi.treasury.listReconciliations(tenantId!),
    enabled: !!tenantId,
  });
  const form = useForm({
    defaultValues: {
      bank_account_id: "",
      statement_date: new Date().toISOString().slice(0, 10),
      statement_balance: "0",
      book_balance: "0",
    },
  });
  const createM = useMutation({
    mutationFn: (d: {
      bank_account_id: string;
      statement_date: string;
      statement_balance: string;
      book_balance: string;
    }) => accountingApi.treasury.createReconciliation(tenantId!, d),
    onSuccess: async () => {
      toast.success("تطبیق ثبت شد");
      setOpen(false);
      form.reset();
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "reconciliations"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

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

  return (
    <div>
      <PageHeader
        title="تطبیق بانکی"
        description="مقایسه مانده صورت‌حساب و دفتر."
        actions={
          <Button type="button" onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            تطبیق جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          {
            key: "statement_date",
            header: "تاریخ صورت‌حساب",
            render: (r) => <JalaliDateText value={String(r.statement_date)} />,
          },
          {
            key: "statement_balance",
            header: "مانده صورت‌حساب",
            render: (r) => formatMoney(String(r.statement_balance)),
          },
          {
            key: "book_balance",
            header: "مانده دفتر",
            render: (r) => formatMoney(String(r.book_balance)),
          },
          {
            key: "difference",
            header: "اختلاف",
            render: (r) => formatMoney(String(r.difference)),
          },
          {
            key: "status",
            header: "وضعیت",
            render: (r) => <Badge>{String(r.status)}</Badge>,
          },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="تطبیقی ثبت نشده" />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="تطبیق بانکی">
        <form className="grid gap-3" onSubmit={form.handleSubmit((d) => createM.mutate(d))}>
          <FormField label="حساب بانکی">
            <Select
              value={form.watch("bank_account_id")}
              onChange={(e) => form.setValue("bank_account_id", e.target.value)}
            >
              <option value="">انتخاب…</option>
              {(banksQ.data ?? []).map((b) => (
                <option key={b.id} value={b.id}>
                  {b.account_number}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="تاریخ">
            <Controller
              control={form.control}
              name="statement_date"
              render={({ field }) => (
                <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
              )}
            />
          </FormField>
          <FormField label="مانده صورت‌حساب">
            <MoneyInput {...form.register("statement_balance")} />
          </FormField>
          <FormField label="مانده دفتر">
            <MoneyInput {...form.register("book_balance")} />
          </FormField>
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createM.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}
