"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 { Plus, Pencil } from "lucide-react";
import { accountingApi, type FiscalPeriod, type FiscalYear } from "@/src/modules/accounting/services/accounting-api";
import { useTenantId } from "@/hooks/useTenantId";
import {
  PageHeader,
  Button,
  Dialog,
  ConfirmDialog,
  Input,
  Label,
  FieldError,
  DataTable,
  EmptyState,
  LoadingState,
  ErrorState,
  Badge,
  DatePicker,
  JalaliDateText,
  Select,
  Checkbox,
} from "@/src/shared/ui";

const yearSchema = z.object({
  name: z.string().min(1, "نام الزامی است"),
  start_date: z.string().min(1, "تاریخ شروع الزامی است"),
  end_date: z.string().min(1, "تاریخ پایان الزامی است"),
  is_current: z.boolean().optional(),
});

const periodSchema = z.object({
  fiscal_year_id: z.string().uuid("سال مالی را انتخاب کنید"),
  name: z.string().min(1, "نام الزامی است"),
  period_number: z.number().int().min(1),
  start_date: z.string().min(1),
  end_date: z.string().min(1),
  is_current: z.boolean().optional(),
});

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

export function FiscalPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [yearOpen, setYearOpen] = useState(false);
  const [periodOpen, setPeriodOpen] = useState(false);
  const [editYear, setEditYear] = useState<FiscalYear | null>(null);
  const [editPeriod, setEditPeriod] = useState<FiscalPeriod | null>(null);
  const [confirm, setConfirm] = useState<
    | { type: "year-close"; id: string }
    | { type: "period"; id: string; action: "lock" | "close" | "reopen" }
    | null
  >(null);

  const yearsQ = useQuery({
    queryKey: ["accounting", tenantId, "fiscal-years"],
    queryFn: () => accountingApi.fiscal.listYears(tenantId!),
    enabled: !!tenantId,
  });
  const periodsQ = useQuery({
    queryKey: ["accounting", tenantId, "fiscal-periods"],
    queryFn: () => accountingApi.fiscal.listPeriods(tenantId!),
    enabled: !!tenantId,
  });

  const yearForm = useForm<z.infer<typeof yearSchema>>({
    resolver: zodResolver(yearSchema),
    defaultValues: { name: "", start_date: "", end_date: "", is_current: true },
  });
  const periodForm = useForm<z.infer<typeof periodSchema>>({
    resolver: zodResolver(periodSchema),
    defaultValues: {
      fiscal_year_id: "",
      name: "",
      period_number: 1,
      start_date: "",
      end_date: "",
      is_current: false,
    },
  });
  const editYearForm = useForm<z.infer<typeof editNameSchema>>({
    resolver: zodResolver(editNameSchema),
  });
  const editPeriodForm = useForm<z.infer<typeof editNameSchema>>({
    resolver: zodResolver(editNameSchema),
  });

  const invalidate = async () => {
    await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "fiscal-years"] });
    await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "fiscal-periods"] });
  };

  const createYear = useMutation({
    mutationFn: (d: z.infer<typeof yearSchema>) => accountingApi.fiscal.createYear(tenantId!, d),
    onSuccess: async () => {
      toast.success("سال مالی ایجاد شد");
      setYearOpen(false);
      yearForm.reset();
      await invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const updateYear = useMutation({
    mutationFn: (d: z.infer<typeof editNameSchema>) =>
      accountingApi.fiscal.updateYear(tenantId!, editYear!.id, { name: d.name }),
    onSuccess: async () => {
      toast.success("سال مالی به‌روز شد");
      setEditYear(null);
      await invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const setCurrentYear = useMutation({
    mutationFn: (id: string) => accountingApi.fiscal.setCurrentYear(tenantId!, id),
    onSuccess: async () => {
      toast.success("سال جاری تنظیم شد");
      await invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const closeYear = useMutation({
    mutationFn: (id: string) => accountingApi.fiscal.closeYear(tenantId!, id),
    onSuccess: async () => {
      toast.success("سال مالی بسته شد");
      setConfirm(null);
      await invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const generatePeriods = useMutation({
    mutationFn: (id: string) => accountingApi.fiscal.generatePeriods(tenantId!, id),
    onSuccess: async (periods) => {
      toast.success(`${periods.length} دوره ایجاد شد`);
      await invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const createPeriod = useMutation({
    mutationFn: (d: z.infer<typeof periodSchema>) => accountingApi.fiscal.createPeriod(tenantId!, d),
    onSuccess: async () => {
      toast.success("دوره مالی ایجاد شد");
      setPeriodOpen(false);
      periodForm.reset();
      await invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const updatePeriod = useMutation({
    mutationFn: (d: z.infer<typeof editNameSchema>) =>
      accountingApi.fiscal.updatePeriod(tenantId!, editPeriod!.id, { name: d.name }),
    onSuccess: async () => {
      toast.success("دوره به‌روز شد");
      setEditPeriod(null);
      await invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const setCurrentPeriod = useMutation({
    mutationFn: (id: string) => accountingApi.fiscal.setCurrentPeriod(tenantId!, id),
    onSuccess: async () => {
      toast.success("دوره جاری تنظیم شد");
      await invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const periodAction = useMutation({
    mutationFn: async () => {
      if (!confirm || confirm.type !== "period") return;
      if (confirm.action === "lock") return accountingApi.fiscal.lockPeriod(tenantId!, confirm.id);
      if (confirm.action === "close") return accountingApi.fiscal.closePeriod(tenantId!, confirm.id);
      return accountingApi.fiscal.reopenPeriod(tenantId!, confirm.id);
    },
    onSuccess: async () => {
      toast.success("وضعیت دوره به‌روز شد");
      setConfirm(null);
      await invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

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

  const yearName = (id: string) => yearsQ.data?.find((y) => y.id === id)?.name ?? id;
  const statusTone = (s: string) =>
    s === "open" ? "success" : s === "locked" ? "warning" : s === "closed" ? "danger" : "default";

  return (
    <div>
      <PageHeader
        title="سال و دوره مالی"
        description="مدیریت تقویم مالی، دوره جاری و قفل/بستن دوره‌ها."
        actions={
          <>
            <Button type="button" variant="outline" onClick={() => setYearOpen(true)}>
              <Plus className="h-4 w-4" />
              سال مالی
            </Button>
            <Button
              type="button"
              onClick={() => {
                const current = yearsQ.data?.find((y) => y.is_current) ?? yearsQ.data?.[0];
                if (current) periodForm.setValue("fiscal_year_id", current.id);
                setPeriodOpen(true);
              }}
              disabled={!yearsQ.data?.length}
            >
              <Plus className="h-4 w-4" />
              دوره مالی
            </Button>
          </>
        }
      />

      <h2 className="mb-3 text-sm font-semibold text-secondary">سال‌های مالی</h2>
      <DataTable
        columns={[
          { key: "name", header: "نام" },
          {
            key: "start_date",
            header: "شروع",
            render: (r) => <JalaliDateText value={String(r.start_date ?? "")} />,
          },
          {
            key: "end_date",
            header: "پایان",
            render: (r) => <JalaliDateText value={String(r.end_date ?? "")} />,
          },
          {
            key: "is_current",
            header: "جاری",
            render: (r) => (r.is_current ? <Badge tone="primary">بله</Badge> : "—"),
          },
          {
            key: "is_closed",
            header: "بسته",
            render: (r) =>
              r.is_closed ? <Badge tone="danger">بسته</Badge> : <Badge tone="success">باز</Badge>,
          },
          {
            key: "actions",
            header: "عملیات",
            render: (r) => {
              const id = String(r.id);
              const closed = Boolean(r.is_closed);
              const current = Boolean(r.is_current);
              return (
                <div className="flex flex-wrap gap-1">
                  {!current && !closed ? (
                    <Button
                      type="button"
                      size="sm"
                      variant="outline"
                      disabled={setCurrentYear.isPending}
                      onClick={() => setCurrentYear.mutate(id)}
                    >
                      جاری
                    </Button>
                  ) : null}
                  {!closed ? (
                    <Button
                      type="button"
                      size="sm"
                      variant="outline"
                      onClick={() => setConfirm({ type: "year-close", id })}
                    >
                      بستن سال
                    </Button>
                  ) : null}
                  <Button
                    type="button"
                    size="sm"
                    variant="secondary"
                    disabled={generatePeriods.isPending}
                    onClick={() => generatePeriods.mutate(id)}
                  >
                    تولید دوره‌ها
                  </Button>
                  <Button
                    type="button"
                    size="sm"
                    variant="ghost"
                    onClick={() => {
                      const y = yearsQ.data?.find((x) => x.id === id);
                      if (y) {
                        setEditYear(y);
                        editYearForm.reset({ name: y.name });
                      }
                    }}
                  >
                    <Pencil className="h-3.5 w-3.5" />
                  </Button>
                </div>
              );
            },
          },
        ]}
        rows={(yearsQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={
          <EmptyState title="سال مالی ندارید" action={<Button onClick={() => setYearOpen(true)}>ایجاد سال</Button>} />
        }
      />

      <h2 className="mb-3 mt-8 text-sm font-semibold text-secondary">دوره‌های مالی</h2>
      <DataTable
        columns={[
          { key: "name", header: "نام" },
          { key: "period_number", header: "شماره" },
          {
            key: "fiscal_year_id",
            header: "سال",
            render: (r) => yearName(String(r.fiscal_year_id)),
          },
          {
            key: "start_date",
            header: "شروع",
            render: (r) => <JalaliDateText value={String(r.start_date ?? "")} />,
          },
          {
            key: "is_current",
            header: "جاری",
            render: (r) => (r.is_current ? <Badge tone="primary">بله</Badge> : "—"),
          },
          {
            key: "status",
            header: "وضعیت",
            render: (r) => <Badge tone={statusTone(String(r.status))}>{String(r.status)}</Badge>,
          },
          {
            key: "actions",
            header: "عملیات",
            render: (r) => {
              const id = String(r.id);
              const status = String(r.status);
              const current = Boolean(r.is_current);
              return (
                <div className="flex flex-wrap gap-1">
                  {!current && status !== "closed" ? (
                    <Button
                      type="button"
                      size="sm"
                      variant="outline"
                      disabled={setCurrentPeriod.isPending}
                      onClick={() => setCurrentPeriod.mutate(id)}
                    >
                      جاری
                    </Button>
                  ) : null}
                  {status === "open" ? (
                    <Button
                      type="button"
                      size="sm"
                      variant="outline"
                      onClick={() => setConfirm({ type: "period", id, action: "lock" })}
                    >
                      قفل
                    </Button>
                  ) : null}
                  {status === "open" || status === "locked" ? (
                    <Button
                      type="button"
                      size="sm"
                      variant="outline"
                      onClick={() => setConfirm({ type: "period", id, action: "close" })}
                    >
                      بستن
                    </Button>
                  ) : null}
                  {status === "closed" || status === "locked" ? (
                    <Button
                      type="button"
                      size="sm"
                      variant="secondary"
                      onClick={() => setConfirm({ type: "period", id, action: "reopen" })}
                    >
                      بازگشایی
                    </Button>
                  ) : null}
                  <Button
                    type="button"
                    size="sm"
                    variant="ghost"
                    onClick={() => {
                      const p = periodsQ.data?.find((x) => x.id === id);
                      if (p) {
                        setEditPeriod(p);
                        editPeriodForm.reset({ name: p.name });
                      }
                    }}
                  >
                    <Pencil className="h-3.5 w-3.5" />
                  </Button>
                </div>
              );
            },
          },
        ]}
        rows={(periodsQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="دوره‌ای ثبت نشده" />}
      />

      <Dialog open={yearOpen} onClose={() => setYearOpen(false)} title="ایجاد سال مالی">
        <form className="space-y-3" onSubmit={yearForm.handleSubmit((d) => createYear.mutate(d))}>
          <div>
            <Label>نام</Label>
            <Input {...yearForm.register("name")} placeholder="۱۴۰۵" />
            <FieldError>{yearForm.formState.errors.name?.message}</FieldError>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <Label>شروع</Label>
              <Controller
                control={yearForm.control}
                name="start_date"
                render={({ field }) => (
                  <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
                )}
              />
              <FieldError>{yearForm.formState.errors.start_date?.message}</FieldError>
            </div>
            <div>
              <Label>پایان</Label>
              <Controller
                control={yearForm.control}
                name="end_date"
                render={({ field }) => (
                  <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
                )}
              />
              <FieldError>{yearForm.formState.errors.end_date?.message}</FieldError>
            </div>
          </div>
          <Checkbox label="سال جاری" {...yearForm.register("is_current")} />
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setYearOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createYear.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>

      <Dialog open={periodOpen} onClose={() => setPeriodOpen(false)} title="ایجاد دوره مالی">
        <form className="space-y-3" onSubmit={periodForm.handleSubmit((d) => createPeriod.mutate(d))}>
          <div>
            <Label>سال مالی</Label>
            <Select {...periodForm.register("fiscal_year_id")}>
              <option value="">انتخاب</option>
              {yearsQ.data?.map((y) => (
                <option key={y.id} value={y.id}>
                  {y.name}
                </option>
              ))}
            </Select>
            <FieldError>{periodForm.formState.errors.fiscal_year_id?.message}</FieldError>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <Label>نام</Label>
              <Input {...periodForm.register("name")} />
              <FieldError>{periodForm.formState.errors.name?.message}</FieldError>
            </div>
            <div>
              <Label>شماره دوره</Label>
              <Input type="number" {...periodForm.register("period_number", { valueAsNumber: true })} />
            </div>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <Label>شروع</Label>
              <Controller
                control={periodForm.control}
                name="start_date"
                render={({ field }) => (
                  <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
                )}
              />
            </div>
            <div>
              <Label>پایان</Label>
              <Controller
                control={periodForm.control}
                name="end_date"
                render={({ field }) => (
                  <DatePicker value={field.value} onChange={field.onChange} onBlur={field.onBlur} name={field.name} />
                )}
              />
            </div>
          </div>
          <Checkbox label="دوره جاری" {...periodForm.register("is_current")} />
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setPeriodOpen(false)}>
              انصراف
            </Button>
            <Button type="submit" disabled={createPeriod.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>

      <Dialog open={!!editYear} onClose={() => setEditYear(null)} title="ویرایش سال مالی">
        <form className="space-y-3" onSubmit={editYearForm.handleSubmit((d) => updateYear.mutate(d))}>
          <div>
            <Label>نام</Label>
            <Input {...editYearForm.register("name")} />
            <FieldError>{editYearForm.formState.errors.name?.message}</FieldError>
          </div>
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setEditYear(null)}>
              انصراف
            </Button>
            <Button type="submit" disabled={updateYear.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>

      <Dialog open={!!editPeriod} onClose={() => setEditPeriod(null)} title="ویرایش دوره مالی">
        <form className="space-y-3" onSubmit={editPeriodForm.handleSubmit((d) => updatePeriod.mutate(d))}>
          <div>
            <Label>نام</Label>
            <Input {...editPeriodForm.register("name")} />
            <FieldError>{editPeriodForm.formState.errors.name?.message}</FieldError>
          </div>
          <div className="flex justify-end gap-2">
            <Button type="button" variant="outline" onClick={() => setEditPeriod(null)}>
              انصراف
            </Button>
            <Button type="submit" disabled={updatePeriod.isPending}>
              ذخیره
            </Button>
          </div>
        </form>
      </Dialog>

      <ConfirmDialog
        open={confirm?.type === "year-close"}
        onClose={() => setConfirm(null)}
        onConfirm={() => confirm?.type === "year-close" && closeYear.mutate(confirm.id)}
        title="بستن سال مالی؟"
        description="پس از بستن، سال دیگر قابل ثبت سند جدید نیست."
        confirmLabel="بستن سال"
        loading={closeYear.isPending}
      />

      <ConfirmDialog
        open={confirm?.type === "period"}
        onClose={() => setConfirm(null)}
        onConfirm={() => periodAction.mutate()}
        title="تغییر وضعیت دوره"
        description="این عملیات روی دوره مالی واقعی اعمال می‌شود."
        confirmLabel="اعمال"
        loading={periodAction.isPending}
      />
    </div>
  );
}
