"use client";

import { useState } from "react";
import { useSearchParams } from "next/navigation";
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 { 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,
  Tabs,
  FormField,
  Select,
  MoneyInput,
  DatePicker,
} from "@/src/shared/ui";

const cashBoxSchema = z.object({
  code: z.string().min(1, "کد الزامی است"),
  name: z.string().min(1, "نام الزامی است"),
  opening_balance: z.string().optional(),
});

const bankSchema = z.object({
  code: z.string().min(1, "کد الزامی است"),
  name: z.string().min(1, "نام الزامی است"),
});

const bankAccountSchema = z.object({
  bank_id: z.string().min(1, "بانک را انتخاب کنید"),
  account_number: z.string().min(1, "شماره حساب الزامی است"),
  iban: z.string().optional(),
});

const receiptSchema = z.object({
  cash_box_id: z.string().min(1, "صندوق را انتخاب کنید"),
  amount: z.string().min(1, "مبلغ الزامی است"),
  debit_account_id: z.string().min(1, "حساب بدهکار را انتخاب کنید"),
  credit_account_id: z.string().min(1, "حساب بستانکار را انتخاب کنید"),
  description: z.string().optional(),
  transaction_date: z.string().optional(),
});

type TabId = "cash-boxes" | "banks" | "bank-accounts" | "receipt";

function isTabId(v: string | null): v is TabId {
  return v === "cash-boxes" || v === "banks" || v === "bank-accounts" || v === "receipt";
}

export function TreasuryPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const searchParams = useSearchParams();
  const initialTab = searchParams.get("tab");
  const [tab, setTab] = useState<TabId>(isTabId(initialTab) ? initialTab : "cash-boxes");
  const [cashBoxOpen, setCashBoxOpen] = useState(false);
  const [bankOpen, setBankOpen] = useState(false);
  const [bankAccountOpen, setBankAccountOpen] = useState(false);

  const cashBoxesQ = useQuery({
    queryKey: ["accounting", tenantId, "cash-boxes"],
    queryFn: () => accountingApi.treasury.listCashBoxes(tenantId!),
    enabled: !!tenantId,
  });
  const banksQ = useQuery({
    queryKey: ["accounting", tenantId, "banks"],
    queryFn: () => accountingApi.treasury.listBanks(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 cashBoxForm = useForm<z.infer<typeof cashBoxSchema>>({
    resolver: zodResolver(cashBoxSchema),
    defaultValues: { code: "", name: "", opening_balance: "0" },
  });
  const bankForm = useForm<z.infer<typeof bankSchema>>({
    resolver: zodResolver(bankSchema),
    defaultValues: { code: "", name: "" },
  });
  const bankAccountForm = useForm<z.infer<typeof bankAccountSchema>>({
    resolver: zodResolver(bankAccountSchema),
    defaultValues: { bank_id: "", account_number: "", iban: "" },
  });
  const receiptForm = useForm<z.infer<typeof receiptSchema>>({
    resolver: zodResolver(receiptSchema),
    defaultValues: {
      cash_box_id: "",
      amount: "",
      debit_account_id: "",
      credit_account_id: "",
      description: "",
      transaction_date: "",
    },
  });

  const postableAccounts = (accountsQ.data ?? []).filter((a) => a.is_postable && a.status === "active");

  const invalidateCashBoxes = () =>
    qc.invalidateQueries({ queryKey: ["accounting", tenantId, "cash-boxes"] });
  const invalidateBanks = () => qc.invalidateQueries({ queryKey: ["accounting", tenantId, "banks"] });
  const invalidateBankAccounts = () =>
    qc.invalidateQueries({ queryKey: ["accounting", tenantId, "bank-accounts"] });

  const createCashBoxM = useMutation({
    mutationFn: (d: z.infer<typeof cashBoxSchema>) =>
      accountingApi.treasury.createCashBox(tenantId!, {
        code: d.code,
        name: d.name,
        opening_balance: parseMoneyInput(d.opening_balance || "0") || "0",
      }),
    onSuccess: async () => {
      toast.success("صندوق ایجاد شد");
      setCashBoxOpen(false);
      cashBoxForm.reset();
      await invalidateCashBoxes();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const archiveCashBoxM = useMutation({
    mutationFn: (id: string) =>
      accountingApi.treasury.updateCashBox(tenantId!, id, { is_active: false }),
    onSuccess: async () => {
      toast.success("صندوق بایگانی شد");
      await invalidateCashBoxes();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const createBankM = useMutation({
    mutationFn: (d: z.infer<typeof bankSchema>) => accountingApi.treasury.createBank(tenantId!, d),
    onSuccess: async () => {
      toast.success("بانک ثبت شد");
      setBankOpen(false);
      bankForm.reset();
      await invalidateBanks();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const createBankAccountM = useMutation({
    mutationFn: (d: z.infer<typeof bankAccountSchema>) =>
      accountingApi.treasury.createBankAccount(tenantId!, {
        bank_id: d.bank_id,
        account_number: d.account_number,
        iban: d.iban || undefined,
      }),
    onSuccess: async () => {
      toast.success("حساب بانکی ثبت شد");
      setBankAccountOpen(false);
      bankAccountForm.reset();
      await invalidateBankAccounts();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const receiptM = useMutation({
    mutationFn: (d: z.infer<typeof receiptSchema>) =>
      accountingApi.treasury.cashReceipt(tenantId!, {
        cash_box_id: d.cash_box_id,
        amount: parseMoneyInput(d.amount) || "0",
        debit_account_id: d.debit_account_id,
        credit_account_id: d.credit_account_id,
        description: d.description || undefined,
        transaction_date: d.transaction_date || undefined,
      }),
    onSuccess: () => {
      toast.success("رسید دریافت نقد ثبت شد");
      receiptForm.reset();
      void invalidateCashBoxes();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  if (!tenantId) return <LoadingState />;
  const loading = cashBoxesQ.isLoading || banksQ.isLoading || bankAccountsQ.isLoading || accountsQ.isLoading;
  if (loading) return <LoadingState />;
  const err = cashBoxesQ.error || banksQ.error || bankAccountsQ.error || accountsQ.error;
  if (err) {
    return (
      <ErrorState
        message={err instanceof Error ? err.message : "خطا"}
        onRetry={() => {
          void cashBoxesQ.refetch();
          void banksQ.refetch();
          void bankAccountsQ.refetch();
          void accountsQ.refetch();
        }}
      />
    );
  }

  const bankName = (id: string) => banksQ.data?.find((b) => b.id === id)?.name ?? id;

  const tabActions: Record<TabId, React.ReactNode> = {
    "cash-boxes": (
      <Button onClick={() => setCashBoxOpen(true)}>
        <Plus className="h-4 w-4" />
        صندوق جدید
      </Button>
    ),
    banks: (
      <Button onClick={() => setBankOpen(true)}>
        <Plus className="h-4 w-4" />
        بانک جدید
      </Button>
    ),
    "bank-accounts": (
      <Button onClick={() => setBankAccountOpen(true)} disabled={!banksQ.data?.length}>
        <Plus className="h-4 w-4" />
        حساب بانکی
      </Button>
    ),
    receipt: null,
  };

  return (
    <div>
      <PageHeader
        title="خزانه"
        description="صندوق‌ها، بانک‌ها و دریافت نقد — داده از API خزانه."
        actions={tabActions[tab]}
      />

      <Tabs
        className="mb-6"
        value={tab}
        onChange={(id) => setTab(id as TabId)}
        items={[
          { id: "cash-boxes", label: "صندوق‌ها" },
          { id: "banks", label: "بانک‌ها" },
          { id: "bank-accounts", label: "حساب‌های بانکی" },
          { id: "receipt", label: "دریافت نقد" },
        ]}
      />

      {tab === "cash-boxes" && (
        <DataTable
          columns={[
            { key: "code", header: "کد" },
            { key: "name", header: "نام" },
            {
              key: "current_balance",
              header: "مانده",
              render: (r) => formatMoney(String(r.current_balance)),
            },
            {
              key: "is_active",
              header: "وضعیت",
              render: (r) => (
                <Badge tone={r.is_active ? "success" : "default"}>
                  {r.is_active ? "فعال" : "غیرفعال"}
                </Badge>
              ),
            },
            {
              key: "actions",
              header: "عملیات",
              render: (r) =>
                r.is_active ? (
                  <Button
                    type="button"
                    size="sm"
                    variant="outline"
                    disabled={archiveCashBoxM.isPending}
                    onClick={() => archiveCashBoxM.mutate(String(r.id))}
                  >
                    بایگانی
                  </Button>
                ) : (
                  "—"
                ),
            },
          ]}
          rows={(cashBoxesQ.data ?? []) as unknown as Record<string, unknown>[]}
          empty={
            <EmptyState action={<Button onClick={() => setCashBoxOpen(true)}>ایجاد صندوق</Button>} />
          }
        />
      )}

      {tab === "banks" && (
        <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={(banksQ.data ?? []) as unknown as Record<string, unknown>[]}
          empty={<EmptyState action={<Button onClick={() => setBankOpen(true)}>ثبت بانک</Button>} />}
        />
      )}

      {tab === "bank-accounts" && (
        <DataTable
          columns={[
            {
              key: "bank_id",
              header: "بانک",
              render: (r) => bankName(String(r.bank_id)),
            },
            { key: "account_number", header: "شماره حساب" },
            { key: "iban", header: "شبا", render: (r) => String(r.iban ?? "—") },
            {
              key: "is_active",
              header: "وضعیت",
              render: (r) => (
                <Badge tone={r.is_active ? "success" : "default"}>
                  {r.is_active ? "فعال" : "غیرفعال"}
                </Badge>
              ),
            },
          ]}
          rows={(bankAccountsQ.data ?? []) as unknown as Record<string, unknown>[]}
          empty={
            <EmptyState action={<Button onClick={() => setBankAccountOpen(true)}>ثبت حساب</Button>} />
          }
        />
      )}

      {tab === "receipt" && (
        <form
          className="mx-auto max-w-lg space-y-4 rounded-2xl border border-[var(--border)] bg-[var(--surface)] p-5"
          onSubmit={receiptForm.handleSubmit((d) => receiptM.mutate(d))}
        >
          <FormField label="صندوق" error={receiptForm.formState.errors.cash_box_id?.message}>
            <Select {...receiptForm.register("cash_box_id")}>
              <option value="">انتخاب صندوق</option>
              {(cashBoxesQ.data ?? [])
                .filter((c) => c.is_active)
                .map((c) => (
                  <option key={c.id} value={c.id}>
                    {c.code} — {c.name}
                  </option>
                ))}
            </Select>
          </FormField>
          <FormField label="مبلغ" error={receiptForm.formState.errors.amount?.message}>
            <MoneyInput {...receiptForm.register("amount")} placeholder="0" />
          </FormField>
          <FormField label="حساب بدهکار" error={receiptForm.formState.errors.debit_account_id?.message}>
            <Select {...receiptForm.register("debit_account_id")}>
              <option value="">انتخاب حساب</option>
              {postableAccounts.map((a) => (
                <option key={a.id} value={a.id}>
                  {a.code} — {a.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="حساب بستانکار" error={receiptForm.formState.errors.credit_account_id?.message}>
            <Select {...receiptForm.register("credit_account_id")}>
              <option value="">انتخاب حساب</option>
              {postableAccounts.map((a) => (
                <option key={a.id} value={a.id}>
                  {a.code} — {a.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="تاریخ (اختیاری)">
            <Controller
              control={receiptForm.control}
              name="transaction_date"
              render={({ field }) => (
                <DatePicker
                  value={field.value}
                  onChange={field.onChange}
                  onBlur={field.onBlur}
                  name={field.name}
                />
              )}
            />
          </FormField>
          <FormField label="شرح (اختیاری)">
            <Input {...receiptForm.register("description")} />
          </FormField>
          <div className="flex justify-end">
            <Button type="submit" disabled={receiptM.isPending}>
              ثبت دریافت
            </Button>
          </div>
        </form>
      )}

      <Dialog open={cashBoxOpen} onClose={() => setCashBoxOpen(false)} title="صندوق جدید">
        <form className="space-y-3" onSubmit={cashBoxForm.handleSubmit((d) => createCashBoxM.mutate(d))}>
          <FormField label="کد" error={cashBoxForm.formState.errors.code?.message}>
            <Input {...cashBoxForm.register("code")} />
          </FormField>
          <FormField label="نام" error={cashBoxForm.formState.errors.name?.message}>
            <Input {...cashBoxForm.register("name")} />
          </FormField>
          <FormField label="مانده اولیه">
            <MoneyInput {...cashBoxForm.register("opening_balance")} />
          </FormField>
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setCashBoxOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createCashBoxM.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>

      <Dialog open={bankOpen} onClose={() => setBankOpen(false)} title="بانک جدید">
        <form className="space-y-3" onSubmit={bankForm.handleSubmit((d) => createBankM.mutate(d))}>
          <FormField label="کد" error={bankForm.formState.errors.code?.message}>
            <Input {...bankForm.register("code")} />
          </FormField>
          <FormField label="نام" error={bankForm.formState.errors.name?.message}>
            <Input {...bankForm.register("name")} />
          </FormField>
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setBankOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createBankM.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>

      <Dialog open={bankAccountOpen} onClose={() => setBankAccountOpen(false)} title="حساب بانکی جدید">
        <form
          className="space-y-3"
          onSubmit={bankAccountForm.handleSubmit((d) => createBankAccountM.mutate(d))}
        >
          <FormField label="بانک" error={bankAccountForm.formState.errors.bank_id?.message}>
            <Select {...bankAccountForm.register("bank_id")}>
              <option value="">انتخاب بانک</option>
              {(banksQ.data ?? []).map((b) => (
                <option key={b.id} value={b.id}>
                  {b.code} — {b.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="شماره حساب" error={bankAccountForm.formState.errors.account_number?.message}>
            <Input {...bankAccountForm.register("account_number")} dir="ltr" />
          </FormField>
          <FormField label="شبا">
            <Input {...bankAccountForm.register("iban")} dir="ltr" placeholder="IR…" />
          </FormField>
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setBankAccountOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createBankAccountM.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}
