"use client";

/**
 * Domain workflow screens that replace generic BusinessDocsPage stubs
 * where dedicated backend models/APIs exist.
 */
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Plus } from "lucide-react";
import { toast } from "sonner";
import { z } from "zod";
import { accountingApi } from "@/src/modules/accounting/services/accounting-api";
import { useTenantId } from "@/hooks/useTenantId";
import { formatMoney, parseMoneyInput } from "@/lib/utils";
import {
  Badge,
  Button,
  DataTable,
  DatePicker,
  Dialog,
  EmptyState,
  ErrorState,
  FormField,
  Input,
  JalaliDateText,
  LoadingState,
  MoneyInput,
  PageHeader,
  Select,
  Textarea,
} from "@/src/shared/ui";

const today = () => new Date().toISOString().slice(0, 10);
const req = z.string().min(1, "الزامی");

function Actions({ onCancel, pending }: { onCancel: () => void; pending?: boolean }) {
  return (
    <div className="flex justify-end gap-2 sm:col-span-2">
      <Button type="button" variant="outline" onClick={onCancel}>
        انصراف
      </Button>
      <Button type="submit" disabled={pending}>
        ذخیره
      </Button>
    </div>
  );
}

/* -------------------- Assets lifecycle -------------------- */

export function AssetTransfersPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const schema = z.object({
    asset_id: req,
    transfer_date: req,
    from_location: z.string().optional(),
    to_location: z.string().optional(),
  });
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: { asset_id: "", transfer_date: today(), from_location: "", to_location: "" },
  });
  const assetsQ = useQuery({
    queryKey: ["accounting", tenantId, "assets"],
    queryFn: () => accountingApi.assets.list(tenantId!),
    enabled: !!tenantId,
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "asset-transfers"],
    queryFn: () => accountingApi.assets.listTransfers(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (v: z.infer<typeof schema>) => accountingApi.assets.createTransfer(tenantId!, v),
    onSuccess: async () => {
      toast.success("انتقال دارایی ثبت شد");
      setOpen(false);
      form.reset({ asset_id: "", transfer_date: today(), from_location: "", to_location: "" });
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "asset-transfers"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || listQ.isLoading || assetsQ.isLoading) return <LoadingState />;
  if (listQ.error || assetsQ.error)
    return <ErrorState message={(listQ.error || assetsQ.error)!.message} onRetry={() => listQ.refetch()} />;
  const names = new Map((assetsQ.data ?? []).map((a) => [a.id, `${a.code} — ${a.name}`]));
  return (
    <div>
      <PageHeader
        title="انتقال دارایی"
        description="ثبت جابه‌جایی مکان/واحد دارایی‌های ثابت."
        actions={
          <Button onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            انتقال جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "asset_id", header: "دارایی", render: (r) => names.get(String(r.asset_id)) || String(r.asset_id) },
          { key: "transfer_date", header: "تاریخ", render: (r) => <JalaliDateText value={String(r.transfer_date)} /> },
          { key: "from_location", header: "از" },
          { key: "to_location", header: "به" },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={
          <EmptyState
            title="انتقالی ثبت نشده"
            action={
              <Button onClick={() => setOpen(true)}>
                <Plus className="h-4 w-4" />
                انتقال جدید
              </Button>
            }
          />
        }
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="ثبت انتقال دارایی" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((v) => createM.mutate(v))}>
          <FormField label="دارایی" error={form.formState.errors.asset_id?.message}>
            <Select {...form.register("asset_id")}>
              <option value="">انتخاب…</option>
              {(assetsQ.data ?? []).map((a) => (
                <option key={a.id} value={a.id}>
                  {a.code} — {a.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="تاریخ">
            <Controller control={form.control} name="transfer_date" render={({ field }) => <DatePicker {...field} />} />
          </FormField>
          <FormField label="مکان مبدأ">
            <Input {...form.register("from_location")} />
          </FormField>
          <FormField label="مکان مقصد">
            <Input {...form.register("to_location")} />
          </FormField>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

export function AssetDisposalsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const schema = z.object({
    asset_id: req,
    disposal_date: req,
    disposal_type: req,
    sale_amount: z.string().optional(),
  });
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: { asset_id: "", disposal_date: today(), disposal_type: "sale", sale_amount: "0" },
  });
  const assetsQ = useQuery({
    queryKey: ["accounting", tenantId, "assets"],
    queryFn: () => accountingApi.assets.list(tenantId!),
    enabled: !!tenantId,
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "asset-disposals"],
    queryFn: () => accountingApi.assets.listDisposals(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (v: z.infer<typeof schema>) =>
      accountingApi.assets.createDisposal(tenantId!, {
        ...v,
        sale_amount: parseMoneyInput(v.sale_amount || "0") || undefined,
      }),
    onSuccess: async () => {
      toast.success("خروج/فروش دارایی ثبت شد");
      setOpen(false);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "asset-disposals"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || listQ.isLoading || assetsQ.isLoading) return <LoadingState />;
  if (listQ.error || assetsQ.error)
    return <ErrorState message={(listQ.error || assetsQ.error)!.message} onRetry={() => listQ.refetch()} />;
  const names = new Map((assetsQ.data ?? []).map((a) => [a.id, `${a.code} — ${a.name}`]));
  return (
    <div>
      <PageHeader
        title="معرفی و فروش دارایی"
        description="ثبت خروج، اسقاط یا فروش دارایی ثابت."
        actions={
          <Button onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            ثبت خروج/فروش
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "asset_id", header: "دارایی", render: (r) => names.get(String(r.asset_id)) || String(r.asset_id) },
          { key: "disposal_date", header: "تاریخ", render: (r) => <JalaliDateText value={String(r.disposal_date)} /> },
          { key: "disposal_type", header: "نوع" },
          { key: "sale_amount", header: "مبلغ فروش", render: (r) => formatMoney(String(r.sale_amount ?? "0")) },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="خروجی ثبت نشده" action={<Button onClick={() => setOpen(true)}>ثبت</Button>} />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="خروج / فروش دارایی" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((v) => createM.mutate(v))}>
          <FormField label="دارایی">
            <Select {...form.register("asset_id")}>
              <option value="">انتخاب…</option>
              {(assetsQ.data ?? []).map((a) => (
                <option key={a.id} value={a.id}>
                  {a.code} — {a.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="تاریخ">
            <Controller control={form.control} name="disposal_date" render={({ field }) => <DatePicker {...field} />} />
          </FormField>
          <FormField label="نوع">
            <Select {...form.register("disposal_type")}>
              <option value="sale">فروش</option>
              <option value="scrap">اسقاط</option>
              <option value="donation">اهدایی</option>
            </Select>
          </FormField>
          <FormField label="مبلغ فروش">
            <MoneyInput {...form.register("sale_amount")} />
          </FormField>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

export function AssetRevaluationsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const schema = z.object({
    asset_id: req,
    revaluation_date: req,
    old_book_value: req,
    new_book_value: req,
  });
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: { asset_id: "", revaluation_date: today(), old_book_value: "0", new_book_value: "0" },
  });
  const assetsQ = useQuery({
    queryKey: ["accounting", tenantId, "assets"],
    queryFn: () => accountingApi.assets.list(tenantId!),
    enabled: !!tenantId,
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "asset-revaluations"],
    queryFn: () => accountingApi.assets.listRevaluations(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (v: z.infer<typeof schema>) =>
      accountingApi.assets.createRevaluation(tenantId!, {
        ...v,
        old_book_value: parseMoneyInput(v.old_book_value) || "0",
        new_book_value: parseMoneyInput(v.new_book_value) || "0",
      }),
    onSuccess: async () => {
      toast.success("ارزش‌گذاری ثبت شد");
      setOpen(false);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "asset-revaluations"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || listQ.isLoading || assetsQ.isLoading) return <LoadingState />;
  if (listQ.error) return <ErrorState message={listQ.error.message} onRetry={() => listQ.refetch()} />;
  const names = new Map((assetsQ.data ?? []).map((a) => [a.id, `${a.code} — ${a.name}`]));
  return (
    <div>
      <PageHeader
        title="ارزش‌گذاری دارایی"
        description="ثبت تجدید ارزیابی ارزش دفتری دارایی."
        actions={
          <Button onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            ارزش‌گذاری جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "asset_id", header: "دارایی", render: (r) => names.get(String(r.asset_id)) || String(r.asset_id) },
          {
            key: "revaluation_date",
            header: "تاریخ",
            render: (r) => <JalaliDateText value={String(r.revaluation_date)} />,
          },
          { key: "old_book_value", header: "ارزش قبلی", render: (r) => formatMoney(String(r.old_book_value)) },
          { key: "new_book_value", header: "ارزش جدید", render: (r) => formatMoney(String(r.new_book_value)) },
          { key: "difference", header: "اختلاف", render: (r) => formatMoney(String(r.difference)) },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="ارزش‌گذاری ثبت نشده" action={<Button onClick={() => setOpen(true)}>ثبت</Button>} />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="ثبت ارزش‌گذاری" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((v) => createM.mutate(v))}>
          <FormField label="دارایی">
            <Select {...form.register("asset_id")}>
              <option value="">انتخاب…</option>
              {(assetsQ.data ?? []).map((a) => (
                <option key={a.id} value={a.id}>
                  {a.code} — {a.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="تاریخ">
            <Controller
              control={form.control}
              name="revaluation_date"
              render={({ field }) => <DatePicker {...field} />}
            />
          </FormField>
          <FormField label="ارزش دفتری قبلی">
            <MoneyInput {...form.register("old_book_value")} />
          </FormField>
          <FormField label="ارزش دفتری جدید">
            <MoneyInput {...form.register("new_book_value")} />
          </FormField>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

export function AssetAccumulatedPage() {
  const { tenantId } = useTenantId();
  const assetsQ = useQuery({
    queryKey: ["accounting", tenantId, "assets"],
    queryFn: () => accountingApi.assets.list(tenantId!),
    enabled: !!tenantId,
  });
  if (!tenantId || assetsQ.isLoading) return <LoadingState />;
  if (assetsQ.error) return <ErrorState message={assetsQ.error.message} onRetry={() => assetsQ.refetch()} />;
  return (
    <div>
      <PageHeader
        title="استهلاک انباشته"
        description="دارایی‌های فعال؛ برنامه استهلاک از صفحه برنامه استهلاک یا دکمه‌های دارایی قابل مشاهده است."
      />
      <DataTable
        columns={[
          { key: "code", header: "کد" },
          { key: "name", header: "نام" },
          { key: "status", header: "وضعیت", render: (r) => <Badge>{String(r.status)}</Badge> },
        ]}
        rows={(assetsQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="دارایی ثبت نشده" />}
      />
    </div>
  );
}

/* -------------------- Payroll masters -------------------- */

export function PayrollContractsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const schema = z.object({
    employee_id: req,
    contract_type: req,
    start_date: req,
    end_date: z.string().optional(),
    base_salary: req,
  });
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: {
      employee_id: "",
      contract_type: "permanent",
      start_date: today(),
      end_date: "",
      base_salary: "0",
    },
  });
  const employeesQ = useQuery({
    queryKey: ["accounting", tenantId, "payroll-employees"],
    queryFn: () => accountingApi.payroll.listEmployees(tenantId!),
    enabled: !!tenantId,
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "payroll-contracts"],
    queryFn: () => accountingApi.payroll.listContracts(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (v: z.infer<typeof schema>) =>
      accountingApi.payroll.createContract(tenantId!, {
        ...v,
        end_date: v.end_date || undefined,
        base_salary: parseMoneyInput(v.base_salary) || "0",
      }),
    onSuccess: async () => {
      toast.success("قرارداد ثبت شد");
      setOpen(false);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "payroll-contracts"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || listQ.isLoading || employeesQ.isLoading) return <LoadingState />;
  if (listQ.error) return <ErrorState message={listQ.error.message} onRetry={() => listQ.refetch()} />;
  const names = new Map((employeesQ.data ?? []).map((e) => [e.id, `${e.code} — ${e.name}`]));
  return (
    <div>
      <PageHeader
        title="تعریف قرارداد"
        description="قراردادهای استخدامی کارکنان و حقوق پایه قراردادی."
        actions={
          <Button onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            قرارداد جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "employee_id", header: "کارمند", render: (r) => names.get(String(r.employee_id)) || String(r.employee_id) },
          { key: "contract_type", header: "نوع" },
          { key: "start_date", header: "شروع", render: (r) => <JalaliDateText value={String(r.start_date)} /> },
          { key: "base_salary", header: "حقوق پایه", render: (r) => formatMoney(String(r.base_salary)) },
          {
            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="قراردادی ثبت نشده" action={<Button onClick={() => setOpen(true)}>ثبت</Button>} />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="قرارداد جدید" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((v) => createM.mutate(v))}>
          <FormField label="کارمند">
            <Select {...form.register("employee_id")}>
              <option value="">انتخاب…</option>
              {(employeesQ.data ?? []).map((e) => (
                <option key={e.id} value={e.id}>
                  {e.code} — {e.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="نوع قرارداد">
            <Select {...form.register("contract_type")}>
              <option value="permanent">دائم</option>
              <option value="temporary">موقت</option>
              <option value="hourly">ساعتی</option>
            </Select>
          </FormField>
          <FormField label="شروع">
            <Controller control={form.control} name="start_date" render={({ field }) => <DatePicker {...field} />} />
          </FormField>
          <FormField label="پایان (اختیاری)">
            <Controller control={form.control} name="end_date" render={({ field }) => <DatePicker {...field} />} />
          </FormField>
          <FormField label="حقوق پایه">
            <MoneyInput {...form.register("base_salary")} />
          </FormField>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

export function PayrollComponentsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const schema = z.object({
    code: req,
    name: req,
    component_type: req,
    is_taxable: z.boolean().optional(),
  });
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: { code: "", name: "", component_type: "earning", is_taxable: true },
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "salary-components"],
    queryFn: () => accountingApi.payroll.listSalaryComponents(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (v: z.infer<typeof schema>) => accountingApi.payroll.createSalaryComponent(tenantId!, v),
    onSuccess: async () => {
      toast.success("قلم حقوق ثبت شد");
      setOpen(false);
      form.reset({ code: "", name: "", component_type: "earning", is_taxable: true });
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "salary-components"] });
    },
    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 onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            قلم جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "code", header: "کد" },
          { key: "name", header: "نام" },
          { key: "component_type", header: "نوع" },
          {
            key: "is_taxable",
            header: "مشمول مالیات",
            render: (r) => (r.is_taxable ? "بله" : "خیر"),
          },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="قلمی تعریف نشده" action={<Button onClick={() => setOpen(true)}>ثبت</Button>} />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="قلم حقوق جدید">
        <form className="grid gap-3" onSubmit={form.handleSubmit((v) => createM.mutate(v))}>
          <FormField label="کد">
            <Input {...form.register("code")} />
          </FormField>
          <FormField label="نام">
            <Input {...form.register("name")} />
          </FormField>
          <FormField label="نوع">
            <Select {...form.register("component_type")}>
              <option value="earning">مزد/مزایا</option>
              <option value="deduction">کسور</option>
              <option value="employer">سهم کارفرما</option>
            </Select>
          </FormField>
          <label className="flex items-center gap-2 text-sm">
            <input type="checkbox" {...form.register("is_taxable")} />
            مشمول مالیات
          </label>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

export function PayrollStructuresPage() {
  return <PayrollComponentsPage />;
}

export function PayrollPaymentsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "payrolls"],
    queryFn: () => accountingApi.payroll.listPayrolls(tenantId!),
    enabled: !!tenantId,
  });
  const employeesQ = useQuery({
    queryKey: ["accounting", tenantId, "payroll-employees"],
    queryFn: () => accountingApi.payroll.listEmployees(tenantId!),
    enabled: !!tenantId,
  });
  const postM = useMutation({
    mutationFn: (id: string) => accountingApi.payroll.post(tenantId!, id),
    onSuccess: async () => {
      toast.success("حقوق به حسابداری ارسال شد");
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "payrolls"] });
    },
    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 names = new Map((employeesQ.data ?? []).map((e) => [e.id, e.name]));
  return (
    <div>
      <PageHeader
        title="پرداخت حقوق"
        description="لیست محاسبات حقوق و ارسال به دفتر از طریق Posting Engine."
      />
      <DataTable
        columns={[
          { key: "employee_id", header: "کارمند", render: (r) => names.get(String(r.employee_id)) || String(r.employee_id) },
          { key: "gross_salary", header: "ناخالص", render: (r) => formatMoney(String(r.gross_salary)) },
          { key: "net_salary", header: "خالص", render: (r) => formatMoney(String(r.net_salary)) },
          { key: "status", header: "وضعیت", render: (r) => <Badge>{String(r.status)}</Badge> },
          {
            key: "id",
            header: "عملیات",
            render: (r) =>
              r.status !== "posted" ? (
                <Button size="sm" variant="outline" onClick={() => postM.mutate(String(r.id))} disabled={postM.isPending}>
                  ثبت حسابداری
                </Button>
              ) : (
                <span className="text-xs text-[var(--muted)]">ارسال شده</span>
              ),
          },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="حقوقی محاسبه نشده — از محاسبه حقوق شروع کنید" />}
      />
    </div>
  );
}

export function PayrollCalculatePage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const schema = z.object({ payroll_period_id: req, employee_id: req });
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: { payroll_period_id: "", employee_id: "" },
  });
  const [result, setResult] = useState<{ id: string; gross_salary: string; net_salary: string; status: string } | null>(
    null
  );
  const employeesQ = useQuery({
    queryKey: ["accounting", tenantId, "payroll-employees"],
    queryFn: () => accountingApi.payroll.listEmployees(tenantId!),
    enabled: !!tenantId,
  });
  const periodsQ = useQuery({
    queryKey: ["accounting", tenantId, "payroll-periods"],
    queryFn: () => accountingApi.payroll.listPeriods(tenantId!),
    enabled: !!tenantId,
  });
  const calcM = useMutation({
    mutationFn: (v: z.infer<typeof schema>) => accountingApi.payroll.calculate(tenantId!, v),
    onSuccess: async (data) => {
      setResult(data);
      toast.success("محاسبه انجام شد");
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "payrolls"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || employeesQ.isLoading || periodsQ.isLoading) return <LoadingState />;
  if (employeesQ.error || periodsQ.error)
    return (
      <ErrorState
        message={(employeesQ.error || periodsQ.error)!.message}
        onRetry={() => {
          employeesQ.refetch();
          periodsQ.refetch();
        }}
      />
    );
  return (
    <div>
      <PageHeader title="محاسبه حقوق" description="اجرای موتور حقوق برای یک کارمند در دوره انتخابی." />
      <form
        className="mb-6 grid max-w-3xl gap-3 rounded-2xl border border-[var(--border)] bg-[var(--surface)] p-4 sm:grid-cols-3"
        onSubmit={form.handleSubmit((v) => calcM.mutate(v))}
      >
        <FormField label="دوره">
          <Select {...form.register("payroll_period_id")}>
            <option value="">انتخاب…</option>
            {(periodsQ.data ?? []).map((p) => (
              <option key={p.id} value={p.id}>
                {p.name}
              </option>
            ))}
          </Select>
        </FormField>
        <FormField label="کارمند">
          <Select {...form.register("employee_id")}>
            <option value="">انتخاب…</option>
            {(employeesQ.data ?? []).map((e) => (
              <option key={e.id} value={e.id}>
                {e.code} — {e.name}
              </option>
            ))}
          </Select>
        </FormField>
        <div className="flex items-end">
          <Button type="submit" disabled={calcM.isPending} className="w-full">
            محاسبه
          </Button>
        </div>
      </form>
      {result ? (
        <div className="rounded-2xl border border-[var(--border)] bg-[var(--surface-muted)] p-4 text-sm">
          ناخالص: {formatMoney(result.gross_salary)} — خالص: {formatMoney(result.net_salary)} — وضعیت: {result.status}
        </div>
      ) : null}
    </div>
  );
}

/* -------------------- Compliance -------------------- */

export function ComplianceApprovalsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const [wfOpen, setWfOpen] = useState(false);
  const reqSchema = z.object({ workflow_id: req, resource_type: req, resource_id: req });
  const wfSchema = z.object({ name: req, resource_type: req });
  const reqForm = useForm<z.infer<typeof reqSchema>>({
    resolver: zodResolver(reqSchema),
    defaultValues: { workflow_id: "", resource_type: "voucher", resource_id: "" },
  });
  const wfForm = useForm<z.infer<typeof wfSchema>>({
    resolver: zodResolver(wfSchema),
    defaultValues: { name: "", resource_type: "voucher" },
  });
  const workflowsQ = useQuery({
    queryKey: ["accounting", tenantId, "workflows"],
    queryFn: () => accountingApi.compliance.listWorkflows(tenantId!),
    enabled: !!tenantId,
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "approvals"],
    queryFn: () => accountingApi.compliance.listApprovals(tenantId!),
    enabled: !!tenantId,
  });
  const createWf = useMutation({
    mutationFn: (v: z.infer<typeof wfSchema>) => accountingApi.compliance.createWorkflow(tenantId!, v),
    onSuccess: async () => {
      toast.success("گردش کار ایجاد شد");
      setWfOpen(false);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "workflows"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  const createReq = useMutation({
    mutationFn: (v: z.infer<typeof reqSchema>) => accountingApi.compliance.requestApproval(tenantId!, v),
    onSuccess: async () => {
      toast.success("درخواست تأیید ثبت شد");
      setOpen(false);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "approvals"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  const approveM = useMutation({
    mutationFn: (id: string) => accountingApi.compliance.approve(tenantId!, id),
    onSuccess: async () => {
      toast.success("تأیید شد");
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "approvals"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  const rejectM = useMutation({
    mutationFn: (id: string) => accountingApi.compliance.reject(tenantId!, id, "رد از رابط کاربری"),
    onSuccess: async () => {
      toast.success("رد شد");
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "approvals"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || listQ.isLoading || workflowsQ.isLoading) return <LoadingState />;
  if (listQ.error) return <ErrorState message={listQ.error.message} onRetry={() => listQ.refetch()} />;
  return (
    <div>
      <PageHeader
        title="گردش تأیید"
        description="تعریف گردش کار تأیید و درخواست/تأیید/رد با کنترل SoD."
        actions={
          <>
            <Button variant="outline" onClick={() => setWfOpen(true)}>
              گردش کار
            </Button>
            <Button onClick={() => setOpen(true)}>
              <Plus className="h-4 w-4" />
              درخواست تأیید
            </Button>
          </>
        }
      />
      <DataTable
        columns={[
          { key: "resource_type", header: "نوع منبع" },
          { key: "resource_id", header: "شناسه" },
          { key: "requested_by", header: "درخواست‌کننده" },
          { key: "status", header: "وضعیت", render: (r) => <Badge>{String(r.status)}</Badge> },
          {
            key: "id",
            header: "عملیات",
            render: (r) =>
              r.status === "pending" ? (
                <div className="flex gap-2">
                  <Button size="sm" onClick={() => approveM.mutate(String(r.id))}>
                    تأیید
                  </Button>
                  <Button size="sm" variant="outline" onClick={() => rejectM.mutate(String(r.id))}>
                    رد
                  </Button>
                </div>
              ) : null,
          },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="درخواستی نیست" action={<Button onClick={() => setOpen(true)}>درخواست</Button>} />}
      />
      <Dialog open={wfOpen} onClose={() => setWfOpen(false)} title="گردش کار جدید">
        <form className="grid gap-3" onSubmit={wfForm.handleSubmit((v) => createWf.mutate(v))}>
          <FormField label="نام">
            <Input {...wfForm.register("name")} />
          </FormField>
          <FormField label="نوع منبع">
            <Input {...wfForm.register("resource_type")} placeholder="voucher" />
          </FormField>
          <Actions onCancel={() => setWfOpen(false)} pending={createWf.isPending} />
        </form>
      </Dialog>
      <Dialog open={open} onClose={() => setOpen(false)} title="درخواست تأیید" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={reqForm.handleSubmit((v) => createReq.mutate(v))}>
          <FormField label="گردش کار">
            <Select {...reqForm.register("workflow_id")}>
              <option value="">انتخاب…</option>
              {(workflowsQ.data ?? []).map((w) => (
                <option key={w.id} value={w.id}>
                  {w.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="نوع منبع">
            <Input {...reqForm.register("resource_type")} />
          </FormField>
          <FormField label="شناسه منبع" className="sm:col-span-2">
            <Input dir="ltr" {...reqForm.register("resource_id")} />
          </FormField>
          <Actions onCancel={() => setOpen(false)} pending={createReq.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

export function ComplianceSodPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const schema = z.object({
    code: req,
    name: req,
    rule_type: req,
    condition_config: req,
    action_config: z.string().optional(),
  });
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: {
      code: "",
      name: "",
      rule_type: "sod",
      condition_config: '{"creator_ne_approver":true}',
      action_config: "",
    },
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "governance-rules"],
    queryFn: () => accountingApi.compliance.listGovernanceRules(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (v: z.infer<typeof schema>) => accountingApi.compliance.createGovernanceRule(tenantId!, v),
    onSuccess: async () => {
      toast.success("قاعده SoD ثبت شد");
      setOpen(false);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "governance-rules"] });
    },
    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="تفکیک وظایف (SoD)"
        description="قواعد حاکمیتی جداسازی نقش ایجادکننده و تأییدکننده."
        actions={
          <Button onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            قاعده جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "code", header: "کد" },
          { key: "name", header: "نام" },
          { key: "rule_type", header: "نوع" },
          { key: "priority", 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="قاعده‌ای نیست" action={<Button onClick={() => setOpen(true)}>ثبت</Button>} />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="قاعده SoD" size="lg">
        <form className="grid gap-3" onSubmit={form.handleSubmit((v) => createM.mutate(v))}>
          <FormField label="کد">
            <Input {...form.register("code")} />
          </FormField>
          <FormField label="نام">
            <Input {...form.register("name")} />
          </FormField>
          <FormField label="پیکربندی شرط (JSON)">
            <Textarea dir="ltr" {...form.register("condition_config")} />
          </FormField>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

export function ComplianceControlsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const schema = z.object({ code: req, name: req, control_type: req, description: z.string().optional() });
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: { code: "", name: "", control_type: "preventive", description: "" },
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "controls"],
    queryFn: () => accountingApi.compliance.listControls(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (v: z.infer<typeof schema>) => accountingApi.compliance.createControl(tenantId!, v),
    onSuccess: async () => {
      toast.success("کنترل ثبت شد");
      setOpen(false);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "controls"] });
    },
    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 onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            کنترل جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "code", header: "کد" },
          { key: "name", header: "نام" },
          { key: "control_type", header: "نوع" },
          { key: "description", header: "شرح" },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="کنترلی نیست" action={<Button onClick={() => setOpen(true)}>ثبت</Button>} />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="کنترل جدید" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((v) => createM.mutate(v))}>
          <FormField label="کد">
            <Input {...form.register("code")} />
          </FormField>
          <FormField label="نام">
            <Input {...form.register("name")} />
          </FormField>
          <FormField label="نوع">
            <Select {...form.register("control_type")}>
              <option value="preventive">پیشگیرانه</option>
              <option value="detective">کشف‌کننده</option>
              <option value="corrective">اصلاحی</option>
            </Select>
          </FormField>
          <FormField label="شرح" className="sm:col-span-2">
            <Input {...form.register("description")} />
          </FormField>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

export function ComplianceViolationsPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const schema = z.object({
    policy_id: req,
    resource_type: req,
    resource_id: req,
    severity: req,
    description: req,
  });
  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    defaultValues: {
      policy_id: "",
      resource_type: "voucher",
      resource_id: "",
      severity: "warning",
      description: "",
    },
  });
  const policiesQ = useQuery({
    queryKey: ["accounting", tenantId, "policies"],
    queryFn: () => accountingApi.compliance.listPolicies(tenantId!),
    enabled: !!tenantId,
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "violations"],
    queryFn: () => accountingApi.compliance.listViolations(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (v: z.infer<typeof schema>) => accountingApi.compliance.createViolation(tenantId!, v),
    onSuccess: async () => {
      toast.success("تخلف ثبت شد");
      setOpen(false);
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "violations"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || listQ.isLoading || policiesQ.isLoading) return <LoadingState />;
  if (listQ.error) return <ErrorState message={listQ.error.message} onRetry={() => listQ.refetch()} />;
  return (
    <div>
      <PageHeader
        title="گزارش تخلفات"
        description="ثبت و پایش نقض سیاست‌های انطباق."
        actions={
          <Button onClick={() => setOpen(true)}>
            <Plus className="h-4 w-4" />
            تخلف جدید
          </Button>
        }
      />
      <DataTable
        columns={[
          { key: "severity", header: "شدت", render: (r) => <Badge tone="warning">{String(r.severity)}</Badge> },
          { key: "resource_type", header: "منبع" },
          { key: "resource_id", header: "شناسه" },
          { key: "description", header: "شرح" },
          { key: "detected_at", header: "زمان", render: (r) => String(r.detected_at).slice(0, 19) },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="تخلفی نیست" action={<Button onClick={() => setOpen(true)}>ثبت</Button>} />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="ثبت تخلف" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((v) => createM.mutate(v))}>
          <FormField label="سیاست">
            <Select {...form.register("policy_id")}>
              <option value="">انتخاب…</option>
              {(policiesQ.data ?? []).map((p) => (
                <option key={p.id} value={p.id}>
                  {p.code} — {p.name}
                </option>
              ))}
            </Select>
          </FormField>
          <FormField label="شدت">
            <Select {...form.register("severity")}>
              <option value="info">اطلاعات</option>
              <option value="warning">هشدار</option>
              <option value="error">خطا</option>
              <option value="critical">بحرانی</option>
            </Select>
          </FormField>
          <FormField label="نوع منبع">
            <Input {...form.register("resource_type")} />
          </FormField>
          <FormField label="شناسه منبع">
            <Input dir="ltr" {...form.register("resource_id")} />
          </FormField>
          <FormField label="شرح" className="sm:col-span-2">
            <Textarea {...form.register("description")} />
          </FormField>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

export function ComplianceRecordsPage() {
  const { tenantId } = useTenantId();
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "audit-records"],
    queryFn: () => accountingApi.compliance.listAudit(tenantId!),
    enabled: !!tenantId,
  });
  if (!tenantId || listQ.isLoading) return <LoadingState />;
  if (listQ.error) return <ErrorState message={listQ.error.message} onRetry={() => listQ.refetch()} />;
  return (
    <div>
      <PageHeader title="اسناد و سوابق انطباق" description="سوابق ممیزی ثبت‌شده در چارچوب انطباق." />
      <DataTable
        columns={[
          { key: "action", header: "عمل" },
          { key: "resource_type", header: "منبع" },
          { key: "actor_user_id", header: "کاربر" },
          { key: "created_at", header: "زمان", render: (r) => String(r.created_at).slice(0, 19) },
        ]}
        rows={(listQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="سابقه‌ای نیست" />}
      />
    </div>
  );
}
