"use client";

import { useEffect } from "react";
import type { ChangeEvent } from "react";
import { Controller, useFieldArray, useForm, useWatch } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import { Plus, Trash2 } from "lucide-react";
import { accountingApi } from "@/lib/accounting-api";
import { useTenantId } from "@/hooks/useTenantId";
import { todayIso } from "@/lib/jalali";
import { formatMoney } from "@/lib/utils";
import { lineBothSidesError, sumVoucherLines, unbalancedMessage } from "@/lib/voucher-balance";
import {
  PageHeader,
  Button,
  Input,
  Label,
  FieldError,
  LoadingState,
  ErrorState,
  Card,
  CardContent,
  DatePicker,
  Select,
  MoneyInput,
} from "@/components/ds";

const lineSchema = z.object({
  account_id: z.string().uuid("حساب معتبر انتخاب کنید"),
  debit: z.string().min(1),
  credit: z.string().min(1),
  description: z.string().optional(),
  cost_center_id: z.string().optional(),
  project_id: z.string().optional(),
});

const schema = z.object({
  fiscal_period_id: z.string().uuid("دوره مالی الزامی است"),
  voucher_number: z.string().optional(),
  voucher_date: z.string().min(1),
  description: z.string().optional(),
  lines: z.array(lineSchema).min(2, "حداقل دو ردیف لازم است"),
});

type FormValues = z.infer<typeof schema>;

export default function NewVoucherPage() {
  const { tenantId } = useTenantId();
  const router = useRouter();
  const form = useForm<FormValues>({
    resolver: zodResolver(schema),
    defaultValues: {
      fiscal_period_id: "",
      voucher_number: "",
      voucher_date: todayIso(),
      description: "",
      lines: [
        { account_id: "", debit: "0", credit: "0", description: "", cost_center_id: "", project_id: "" },
        { account_id: "", debit: "0", credit: "0", description: "", cost_center_id: "", project_id: "" },
      ],
    },
  });
  const { fields, append, remove } = useFieldArray({ control: form.control, name: "lines" });

  const periodsQ = useQuery({
    queryKey: ["accounting", tenantId, "fiscal-periods"],
    queryFn: () => accountingApi.fiscal.listPeriods(tenantId!),
    enabled: !!tenantId,
  });
  const nextNumberQ = useQuery({
    queryKey: ["accounting", tenantId, "seq", "voucher"],
    queryFn: () => accountingApi.setup.peekNumber(tenantId!, "voucher"),
    enabled: !!tenantId,
  });
  const accountsQ = useQuery({
    queryKey: ["accounting", tenantId, "accounts"],
    queryFn: () => accountingApi.accounts.list(tenantId!),
    enabled: !!tenantId,
  });
  const costCentersQ = useQuery({
    queryKey: ["accounting", tenantId, "cost-centers"],
    queryFn: () => accountingApi.costCenters.list(tenantId!),
    enabled: !!tenantId,
  });
  const projectsQ = useQuery({
    queryKey: ["accounting", tenantId, "projects"],
    queryFn: () => accountingApi.projects.list(tenantId!),
    enabled: !!tenantId,
  });

  useEffect(() => {
    if (nextNumberQ.data?.preview && !form.getValues("voucher_number")) {
      form.setValue("voucher_number", nextNumberQ.data.preview);
    }
  }, [nextNumberQ.data, form]);

  const createM = useMutation({
    mutationFn: (data: FormValues) => {
      const bal = sumVoucherLines(data.lines);
      if (!bal.isBalanced) {
        throw new Error(unbalancedMessage(bal.debit, bal.credit));
      }
      for (let i = 0; i < data.lines.length; i++) {
        const err = lineBothSidesError(data.lines[i].debit, data.lines[i].credit);
        if (err) throw new Error(`ردیف ${i + 1}: ${err}`);
      }
      return accountingApi.vouchers.create(tenantId!, {
        fiscal_period_id: data.fiscal_period_id,
        voucher_number: data.voucher_number?.trim() || undefined,
        voucher_date: data.voucher_date,
        description: data.description || undefined,
        source_module: "manual",
        lines: data.lines.map((l) => ({
          account_id: l.account_id,
          debit: l.debit || "0",
          credit: l.credit || "0",
          description: l.description || undefined,
          cost_center_id: l.cost_center_id || null,
          project_id: l.project_id || null,
        })),
      });
    },
    onSuccess: (v) => {
      toast.success("سند ایجاد شد");
      router.push(`/accounting/vouchers/${v.id}`);
    },
    onError: (e: Error) => toast.error(e.message),
  });

  // useWatch (not useMemo on watch) — RHF mutates lines in place; memo would freeze at 0/0.
  const watchedLines = useWatch({ control: form.control, name: "lines" });
  const balance = sumVoucherLines(watchedLines);

  if (!tenantId || periodsQ.isLoading || accountsQ.isLoading) return <LoadingState />;
  if (periodsQ.error || accountsQ.error) {
    return (
      <ErrorState
        message={(periodsQ.error || accountsQ.error)?.message || "خطا"}
        onRetry={() => {
          void periodsQ.refetch();
          void accountsQ.refetch();
        }}
      />
    );
  }

  const postable = (accountsQ.data ?? []).filter((a) => a.is_postable);
  const activeCostCenters = (costCentersQ.data ?? []).filter((c) => c.is_active);
  const activeProjects = (projectsQ.data ?? []).filter((p) => p.is_active);
  const openPeriods = (periodsQ.data ?? []).filter((p) => p.status === "open" || p.status === "locked");

  return (
    <div>
      <PageHeader
        title="سند حسابداری جدید"
        description="ایجاد سند پیش‌نویس — ثبت قطعی فقط از طریق Posting Engine."
      />
      <form className="space-y-6" onSubmit={form.handleSubmit((d) => createM.mutate(d))}>
        <Card>
          <CardContent className="grid gap-4 pt-6 sm:grid-cols-2">
            <div>
              <Label>دوره مالی</Label>
              <select
                className="mt-1 w-full rounded-xl border border-[var(--border)] bg-[var(--surface)] px-3 py-2 text-sm"
                {...form.register("fiscal_period_id")}
              >
                <option value="">انتخاب دوره</option>
                {(periodsQ.data ?? []).map((p) => (
                  <option key={p.id} value={p.id}>
                    {p.name} ({p.status})
                  </option>
                ))}
              </select>
              <FieldError>{form.formState.errors.fiscal_period_id?.message}</FieldError>
              {!openPeriods.length ? (
                <p className="mt-1 text-xs text-amber-600">ابتدا یک دوره مالی باز ایجاد کنید.</p>
              ) : null}
            </div>
            <div>
              <Label>شماره سند</Label>
              <Input className="mt-1" placeholder="خودکار" {...form.register("voucher_number")} />
              <p className="mt-1 text-xs text-[var(--muted)]">
                پیشنهاد سیستم: {nextNumberQ.data?.preview ?? "…"} — خالی بگذارید تا هنگام ذخیره تخصیص داده شود.
              </p>
              <FieldError>{form.formState.errors.voucher_number?.message}</FieldError>
            </div>
            <div>
              <Label>تاریخ</Label>
              <Controller
                control={form.control}
                name="voucher_date"
                render={({ field }) => (
                  <DatePicker
                    className="mt-1"
                    value={field.value}
                    onChange={field.onChange}
                    onBlur={field.onBlur}
                    name={field.name}
                  />
                )}
              />
              <FieldError>{form.formState.errors.voucher_date?.message}</FieldError>
            </div>
            <div>
              <Label>شرح</Label>
              <Input className="mt-1" {...form.register("description")} />
            </div>
          </CardContent>
        </Card>

        <Card>
          <CardContent className="space-y-3 pt-6">
            <div className="flex items-center justify-between">
              <h2 className="font-semibold text-secondary">ردیف‌های سند</h2>
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={() =>
                  append({
                    account_id: "",
                    debit: "0",
                    credit: "0",
                    description: "",
                    cost_center_id: "",
                    project_id: "",
                  })
                }
              >
                <Plus className="h-4 w-4" />
                ردیف
              </Button>
            </div>
            {fields.map((field, index) => {
              const lineErr = lineBothSidesError(
                watchedLines?.[index]?.debit ?? "0",
                watchedLines?.[index]?.credit ?? "0"
              );
              return (
              <div
                key={field.id}
                className={`grid gap-2 rounded-xl border p-3 sm:grid-cols-12 ${
                  lineErr ? "border-red-300 bg-red-50/40" : "border-[var(--border)]"
                }`}
              >
                <div className="sm:col-span-3">
                  <Label>حساب</Label>
                  <Select className="mt-1" {...form.register(`lines.${index}.account_id`)}>
                    <option value="">انتخاب حساب</option>
                    {postable.map((a) => (
                      <option key={a.id} value={a.id}>
                        {a.code} — {a.name}
                      </option>
                    ))}
                  </Select>
                </div>
                <div className="sm:col-span-2">
                  <Label>بدهکار</Label>
                  <Controller
                    control={form.control}
                    name={`lines.${index}.debit`}
                    render={({ field }) => (
                      <MoneyInput
                        className="mt-1"
                        name={field.name}
                        ref={field.ref}
                        value={field.value ?? "0"}
                        onBlur={field.onBlur}
                        onChange={(e) => {
                          const next =
                            typeof e === "object" && e && "target" in e
                              ? String((e as ChangeEvent<HTMLInputElement>).target.value)
                              : String(e ?? "0");
                          field.onChange(next);
                        }}
                      />
                    )}
                  />
                </div>
                <div className="sm:col-span-2">
                  <Label>بستانکار</Label>
                  <Controller
                    control={form.control}
                    name={`lines.${index}.credit`}
                    render={({ field }) => (
                      <MoneyInput
                        className="mt-1"
                        name={field.name}
                        ref={field.ref}
                        value={field.value ?? "0"}
                        onBlur={field.onBlur}
                        onChange={(e) => {
                          const next =
                            typeof e === "object" && e && "target" in e
                              ? String((e as ChangeEvent<HTMLInputElement>).target.value)
                              : String(e ?? "0");
                          field.onChange(next);
                        }}
                      />
                    )}
                  />
                </div>
                <div className="sm:col-span-2">
                  <Label>مرکز هزینه</Label>
                  <Select className="mt-1" {...form.register(`lines.${index}.cost_center_id`)}>
                    <option value="">—</option>
                    {activeCostCenters.map((c) => (
                      <option key={c.id} value={c.id}>
                        {c.code} — {c.name}
                      </option>
                    ))}
                  </Select>
                </div>
                <div className="sm:col-span-2">
                  <Label>پروژه</Label>
                  <Select className="mt-1" {...form.register(`lines.${index}.project_id`)}>
                    <option value="">—</option>
                    {activeProjects.map((p) => (
                      <option key={p.id} value={p.id}>
                        {p.code} — {p.name}
                      </option>
                    ))}
                  </Select>
                </div>
                <div className="sm:col-span-2">
                  <Label>شرح</Label>
                  <Input className="mt-1" {...form.register(`lines.${index}.description`)} />
                </div>
                <div className="flex items-end sm:col-span-1">
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    disabled={fields.length <= 2}
                    onClick={() => remove(index)}
                    aria-label="حذف ردیف"
                  >
                    <Trash2 className="h-4 w-4" />
                  </Button>
                </div>
                {lineErr ? (
                  <p className="sm:col-span-12 text-xs text-red-700">ردیف {index + 1}: {lineErr}</p>
                ) : null}
              </div>
              );
            })}
            <FieldError>{form.formState.errors.lines?.message || form.formState.errors.lines?.root?.message}</FieldError>
            <div
              className={`rounded-xl border p-3 text-sm ${
                balance.isBalanced
                  ? "border-emerald-200 bg-emerald-50 text-emerald-800"
                  : "border-red-200 bg-red-50 text-red-800"
              }`}
            >
              <div className="flex flex-wrap gap-4">
                <span>جمع بدهکار: {formatMoney(String(balance.debit))}</span>
                <span>جمع بستانکار: {formatMoney(String(balance.credit))}</span>
                <span>اختلاف: {formatMoney(String(Math.abs(balance.difference)))}</span>
                <span className="font-semibold">
                  {balance.isBalanced
                    ? "متوازن ✓"
                    : !balance.hasAmount
                      ? "مبالغ ردیف‌ها را وارد کنید"
                      : "نامتوازن — ثبت مجاز نیست"}
                </span>
              </div>
              {balance.hasAmount && !balance.isBalanced ? (
                <p className="mt-2 text-xs">{unbalancedMessage(balance.debit, balance.credit)}</p>
              ) : null}
            </div>
          </CardContent>
        </Card>

        <div className="flex justify-end gap-2">
          <Button type="button" variant="outline" onClick={() => router.push("/accounting/vouchers")}>
            انصراف
          </Button>
          <Button type="submit" disabled={createM.isPending || !balance.isBalanced || (watchedLines ?? []).some((l) => !!lineBothSidesError(l.debit, l.credit))}>
            ذخیره پیش‌نویس
          </Button>
        </div>
      </form>
    </div>
  );
}
