"use client";

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,
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  DataTable,
  DatePicker,
  Dialog,
  EmptyState,
  ErrorState,
  FormField,
  Input,
  JalaliDateText,
  LoadingState,
  MoneyInput,
  PageHeader,
  Select,
  StatCard,
  Textarea,
} from "@/src/shared/ui";
import { PartyCombobox } from "@/src/modules/accounting/components/EntityCombobox";

const today = () => new Date().toISOString().slice(0, 10);
const requiredText = z.string().min(1, "این فیلد الزامی است");

function Actions({
  onCancel,
  pending,
  submitLabel = "ذخیره",
}: {
  onCancel: () => void;
  pending: boolean;
  submitLabel?: string;
}) {
  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}>
        {submitLabel}
      </Button>
    </div>
  );
}

const employeeSchema = z.object({
  employee_code: requiredText,
  first_name: requiredText,
  last_name: requiredText,
  base_salary: requiredText,
  department_id: z.string(),
});

export function PayrollEmployeesPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const form = useForm<z.infer<typeof employeeSchema>>({
    resolver: zodResolver(employeeSchema),
    defaultValues: { employee_code: "", first_name: "", last_name: "", base_salary: "0", department_id: "" },
  });
  const employeesQ = useQuery({
    queryKey: ["accounting", tenantId, "payroll-employees"],
    queryFn: () => accountingApi.payroll.listEmployees(tenantId!),
    enabled: !!tenantId,
  });
  const departmentsQ = useQuery({
    queryKey: ["accounting", tenantId, "payroll-departments"],
    queryFn: () => accountingApi.payroll.listDepartments(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (values: z.infer<typeof employeeSchema>) =>
      accountingApi.payroll.createEmployee(tenantId!, {
        ...values,
        department_id: values.department_id || undefined,
      }),
    onSuccess: async () => {
      toast.success("کارمند ثبت شد");
      setOpen(false);
      form.reset();
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "payroll-employees"] });
    },
    onError: (error: Error) => toast.error(error.message),
  });
  if (!tenantId || employeesQ.isLoading || departmentsQ.isLoading) return <LoadingState />;
  if (employeesQ.error || departmentsQ.error) {
    const error = employeesQ.error || departmentsQ.error;
    return <ErrorState message={error!.message} onRetry={() => { employeesQ.refetch(); departmentsQ.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: "نام و نام خانوادگی" }]}
        rows={employeesQ.data as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="کارمندی ثبت نشده" />}
      />
      <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.employee_code?.message}><Input {...form.register("employee_code")} /></FormField>
          <FormField label="نام" error={form.formState.errors.first_name?.message}><Input {...form.register("first_name")} /></FormField>
          <FormField label="نام خانوادگی" error={form.formState.errors.last_name?.message}><Input {...form.register("last_name")} /></FormField>
          <FormField label="حقوق پایه" error={form.formState.errors.base_salary?.message}><MoneyInput {...form.register("base_salary")} /></FormField>
          <FormField label="واحد سازمانی">
            <Select {...form.register("department_id")}>
              <option value="">بدون واحد</option>
              {(departmentsQ.data ?? []).map((d) => <option key={d.id} value={d.id}>{d.name}</option>)}
            </Select>
          </FormField>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

const policySchema = z.object({
  code: requiredText,
  name: requiredText,
  policy_type: requiredText,
  rules_config: requiredText.refine((value) => {
    try { JSON.parse(value); return true; } catch { return false; }
  }, "JSON معتبر وارد کنید"),
});

export function CompliancePoliciesPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const form = useForm<z.infer<typeof policySchema>>({
    resolver: zodResolver(policySchema),
    defaultValues: { code: "", name: "", policy_type: "", rules_config: "{}" },
  });
  const listQ = useQuery({
    queryKey: ["accounting", tenantId, "compliance-policies"],
    queryFn: () => accountingApi.compliance.listPolicies(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (values: z.infer<typeof policySchema>) => accountingApi.compliance.createPolicy(tenantId!, values),
    onSuccess: async () => {
      toast.success("سیاست ثبت شد");
      setOpen(false);
      form.reset();
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "compliance-policies"] });
    },
    onError: (error: Error) => toast.error(error.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: "policy_type", header: "نوع" },
          { key: "is_active", header: "وضعیت", render: (r) => <Badge tone={r.is_active ? "success" : "default"}>{r.is_active ? "فعال" : "غیرفعال"}</Badge> },
        ]}
        rows={listQ.data as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="سیاستی ثبت نشده" />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="سیاست جدید" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={form.handleSubmit((v) => createM.mutate(v))}>
          <FormField label="کد" error={form.formState.errors.code?.message}><Input {...form.register("code")} /></FormField>
          <FormField label="نام" error={form.formState.errors.name?.message}><Input {...form.register("name")} /></FormField>
          <FormField label="نوع سیاست" error={form.formState.errors.policy_type?.message}><Input {...form.register("policy_type")} placeholder="tax, audit, ..." /></FormField>
          <div className="sm:col-span-2"><FormField label="پیکربندی قواعد (JSON)" error={form.formState.errors.rules_config?.message}><Textarea dir="ltr" {...form.register("rules_config")} /></FormField></div>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

const riskSchema = z.object({
  code: requiredText,
  title: requiredText,
  risk_category: requiredText,
  risk_level: z.enum(["low", "medium", "high", "critical"]),
  risk_score: z.number().int().min(0),
});

export function ComplianceRisksPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const form = useForm<z.infer<typeof riskSchema>>({
    resolver: zodResolver(riskSchema),
    defaultValues: { code: "", title: "", risk_category: "", risk_level: "low", risk_score: 0 },
  });
  const listQ = useQuery({ queryKey: ["accounting", tenantId, "compliance-risks"], queryFn: () => accountingApi.compliance.listRisks(tenantId!), enabled: !!tenantId });
  const createM = useMutation({
    mutationFn: (values: z.infer<typeof riskSchema>) => accountingApi.compliance.createRisk(tenantId!, values),
    onSuccess: async () => {
      toast.success("ریسک ثبت شد");
      setOpen(false);
      form.reset();
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "compliance-risks"] });
    },
    onError: (error: Error) => toast.error(error.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: "title", header: "عنوان" }, { key: "risk_category", header: "دسته" },
          { key: "risk_level", header: "سطح", render: (r) => <Badge tone={r.risk_level === "critical" || r.risk_level === "high" ? "danger" : r.risk_level === "medium" ? "warning" : "default"}>{String(r.risk_level)}</Badge> },
          { key: "risk_score", header: "امتیاز" }, { key: "is_resolved", header: "وضعیت", render: (r) => r.is_resolved ? "رفع شده" : "باز" },
        ]}
        rows={listQ.data as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="ریسکی ثبت نشده" />}
      />
      <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.code?.message}><Input {...form.register("code")} /></FormField>
          <FormField label="عنوان" error={form.formState.errors.title?.message}><Input {...form.register("title")} /></FormField>
          <FormField label="دسته ریسک" error={form.formState.errors.risk_category?.message}><Input {...form.register("risk_category")} /></FormField>
          <FormField label="سطح"><Select {...form.register("risk_level")}><option value="low">کم</option><option value="medium">متوسط</option><option value="high">زیاد</option><option value="critical">بحرانی</option></Select></FormField>
          <FormField label="امتیاز" error={form.formState.errors.risk_score?.message}><Input type="number" min={0} {...form.register("risk_score", { valueAsNumber: true })} /></FormField>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

const settlementSchema = z.object({
  settlement_number: requiredText,
  settlement_date: requiredText,
  settlement_type: z.enum(["receipt", "payment"]),
  party_id: requiredText,
  total_amount: requiredText,
  allocations: requiredText.refine((value) => {
    try { return Array.isArray(JSON.parse(value)); } catch { return false; }
  }, "آرایه JSON معتبر وارد کنید"),
});

export function SettlementsPage({ partyType }: { partyType: "customer" | "supplier" }) {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const form = useForm<z.infer<typeof settlementSchema>>({
    resolver: zodResolver(settlementSchema),
    defaultValues: { settlement_number: "", settlement_date: today(), settlement_type: partyType === "customer" ? "receipt" : "payment", party_id: "", total_amount: "0", allocations: "[]" },
  });
  const listQ = useQuery({ queryKey: ["accounting", tenantId, "settlements", partyType], queryFn: () => accountingApi.settlements.list(tenantId!, partyType), enabled: !!tenantId });
  const partiesQ = useQuery({
    queryKey: ["accounting", tenantId, partyType === "customer" ? "customers" : "suppliers"],
    queryFn: () => partyType === "customer" ? accountingApi.customers.list(tenantId!) : accountingApi.suppliers.list(tenantId!),
    enabled: !!tenantId,
  });
  const createM = useMutation({
    mutationFn: (values: z.infer<typeof settlementSchema>) => accountingApi.settlements.create(tenantId!, {
      ...values,
      total_amount: parseMoneyInput(values.total_amount) || "0",
      party_type: partyType,
      allocations: JSON.parse(values.allocations) as { invoice_id?: string; amount: string }[],
    }),
    onSuccess: async () => {
      toast.success("تسویه ثبت شد");
      setOpen(false);
      form.reset();
      await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "settlements", partyType] });
    },
    onError: (error: Error) => toast.error(error.message),
  });
  if (!tenantId || listQ.isLoading || partiesQ.isLoading) return <LoadingState />;
  if (listQ.error || partiesQ.error) return <ErrorState message={(listQ.error || partiesQ.error)!.message} onRetry={() => { listQ.refetch(); partiesQ.refetch(); }} />;
  const partyNames = new Map((partiesQ.data ?? []).map((p) => [p.id, p.name]));
  return (
    <div>
      <PageHeader title={partyType === "customer" ? "تسویه حساب مشتریان" : "تسویه با تأمین‌کنندگان"} description="ثبت تسویه و تخصیص آن به اسناد طرف حساب." actions={<Button onClick={() => setOpen(true)}><Plus className="h-4 w-4" />تسویه جدید</Button>} />
      <DataTable
        columns={[
          { key: "settlement_number", header: "شماره" }, { key: "settlement_date", header: "تاریخ", render: (r) => <JalaliDateText value={String(r.settlement_date)} /> },
          { key: "party_id", header: "طرف حساب", render: (r) => partyNames.get(String(r.party_id)) || String(r.party_id) },
          { key: "settlement_type", header: "نوع" }, { key: "total_amount", header: "مبلغ", render: (r) => formatMoney(String(r.total_amount)) },
          { key: "status", header: "وضعیت", render: (r) => <Badge>{String(r.status)}</Badge> },
        ]}
        rows={listQ.data as unknown as Record<string, unknown>[]}
        empty={
          <EmptyState
            title="تسویه‌ای ثبت نشده"
            description="برای شروع، تسویه جدید ثبت کنید."
            action={
              <Button type="button" onClick={() => setOpen(true)}>
                <Plus className="h-4 w-4" />
                تسویه جدید
              </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.settlement_number?.message}><Input {...form.register("settlement_number")} /></FormField>
          <FormField label="تاریخ" error={form.formState.errors.settlement_date?.message}><Controller control={form.control} name="settlement_date" render={({ field }) => <DatePicker {...field} />} /></FormField>
          <FormField label="نوع"><Select {...form.register("settlement_type")}><option value="receipt">دریافت</option><option value="payment">پرداخت</option></Select></FormField>
          <FormField label="طرف حساب" error={form.formState.errors.party_id?.message}>
            <PartyCombobox
              module={partyType === "customer" ? "sales" : "purchase"}
              valueName={partyNames.get(form.watch("party_id")) || undefined}
              onChange={(party) => form.setValue("party_id", party?.id || "", { shouldValidate: true })}
            />
          </FormField>
          <FormField label="مبلغ کل" error={form.formState.errors.total_amount?.message}><MoneyInput {...form.register("total_amount")} /></FormField>
          <div className="sm:col-span-2"><FormField label="تخصیص‌ها (JSON)" error={form.formState.errors.allocations?.message}><Textarea dir="ltr" placeholder='[{"invoice_id":"...","amount":"1000"}]' {...form.register("allocations")} /></FormField></div>
          <Actions onCancel={() => setOpen(false)} pending={createM.isPending} />
        </form>
      </Dialog>
    </div>
  );
}

const documentSchema = z.object({
  number: requiredText,
  doc_date: requiredText,
  party_name: z.string(),
  party_id: z.string().optional(),
  amount: requiredText,
  description: z.string(),
});
const salesPostSchema = z.object({ source_document_id: requiredText, total_amount: requiredText, discount_amount: requiredText, tax_amount: requiredText, profile_id: z.string() });

export function SalesInvoiceAccountingPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [createOpen, setCreateOpen] = useState(false);
  const [profileOpen, setProfileOpen] = useState(false);
  const [postOpen, setPostOpen] = useState(false);
  const [preview, setPreview] = useState<{ is_balanced: boolean; total_debit: string; total_credit: string } | null>(null);
  const docForm = useForm<z.infer<typeof documentSchema>>({ resolver: zodResolver(documentSchema), defaultValues: { number: "", doc_date: today(), party_name: "", amount: "0", description: "" } });
  const profileForm = useForm({ defaultValues: { name: "" } });
  const postForm = useForm<z.infer<typeof salesPostSchema>>({ resolver: zodResolver(salesPostSchema), defaultValues: { source_document_id: "", total_amount: "0", discount_amount: "0", tax_amount: "0", profile_id: "" } });
  const docsQ = useQuery({ queryKey: ["accounting", tenantId, "ops-docs", "sales", "invoice"], queryFn: () => accountingApi.ops.listDocuments(tenantId!, "sales", "invoice"), enabled: !!tenantId });
  const profilesQ = useQuery({ queryKey: ["accounting", tenantId, "sales-profiles"], queryFn: () => accountingApi.salesAccounting.listProfiles(tenantId!), enabled: !!tenantId });
  const createDocM = useMutation({
    mutationFn: (v: z.infer<typeof documentSchema>) => accountingApi.ops.createDocument(tenantId!, { module: "sales", doc_type: "invoice", status: "draft", ...v }),
    onSuccess: async () => { toast.success("فاکتور ثبت شد"); setCreateOpen(false); docForm.reset(); await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "ops-docs", "sales", "invoice"] }); },
    onError: (e: Error) => toast.error(e.message),
  });
  const createProfileM = useMutation({
    mutationFn: (v: { name: string }) => accountingApi.salesAccounting.createProfile(tenantId!, { name: v.name, document_type: "invoice" }),
    onSuccess: async () => { toast.success("پروفایل ثبت شد"); setProfileOpen(false); profileForm.reset(); await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "sales-profiles"] }); },
    onError: (e: Error) => toast.error(e.message),
  });
  const previewM = useMutation({
    mutationFn: (v: z.infer<typeof salesPostSchema>) => accountingApi.salesAccounting.preview(tenantId!, { document_type: "invoice", total_amount: v.total_amount, discount_amount: v.discount_amount, tax_amount: v.tax_amount, profile_id: v.profile_id || undefined }),
    onSuccess: (data) => { setPreview(data); toast.success("پیش‌نمایش آماده شد"); },
    onError: (e: Error) => toast.error(e.message),
  });
  const postM = useMutation({
    mutationFn: (v: z.infer<typeof salesPostSchema>) => accountingApi.salesAccounting.post(tenantId!, { document_type: "invoice", ...v, profile_id: v.profile_id || undefined }),
    onSuccess: (data) => { toast.success(`سند ${data.voucher_number} ثبت شد`); setPostOpen(false); setPreview(null); },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || docsQ.isLoading || profilesQ.isLoading) return <LoadingState />;
  if (docsQ.error || profilesQ.error) return <ErrorState message={(docsQ.error || profilesQ.error)!.message} onRetry={() => { docsQ.refetch(); profilesQ.refetch(); }} />;
  const openPosting = (row: Record<string, unknown>) => {
    postForm.reset({ source_document_id: String(row.id), total_amount: String(row.amount || "0"), discount_amount: "0", tax_amount: "0", profile_id: "" });
    setPreview(null);
    setPostOpen(true);
  };
  return (
    <div>
      <PageHeader title="فاکتور فروش و ثبت حسابداری" description="ثبت فاکتور عملیاتی، پیش‌نمایش و ارسال به دفتر حسابداری." actions={<><Button variant="outline" onClick={() => setProfileOpen(true)}>پروفایل ثبت</Button><Button onClick={() => setCreateOpen(true)}><Plus className="h-4 w-4" />فاکتور جدید</Button></>} />
      <DataTable
        columns={[
          { key: "number", header: "شماره" }, { key: "doc_date", header: "تاریخ", render: (r) => <JalaliDateText value={String(r.doc_date)} /> },
          { key: "party_name", header: "مشتری" }, { key: "amount", header: "مبلغ", render: (r) => formatMoney(String(r.amount)) },
          { key: "status", header: "وضعیت", render: (r) => <Badge>{String(r.status)}</Badge> },
          { key: "actions", header: "عملیات", render: (r) => <Button size="sm" variant="outline" onClick={() => openPosting(r)}>ثبت حسابداری</Button> },
        ]}
        rows={docsQ.data as unknown as Record<string, unknown>[]}
        empty={
          <EmptyState
            title="فاکتور فروشی ثبت نشده"
            description="برای شروع، فاکتور جدید ثبت کنید."
            action={
              <Button type="button" onClick={() => setCreateOpen(true)}>
                <Plus className="h-4 w-4" />
                فاکتور جدید
              </Button>
            }
          />
        }
      />
      <DocumentDialog open={createOpen} onClose={() => setCreateOpen(false)} title="ثبت فاکتور فروش" form={docForm} mutation={createDocM} partyModule="sales" />
      <Dialog open={profileOpen} onClose={() => setProfileOpen(false)} title="پروفایل ثبت فروش">
        <form className="grid gap-3" onSubmit={profileForm.handleSubmit((v) => createProfileM.mutate(v))}><FormField label="نام پروفایل"><Input {...profileForm.register("name", { required: true })} /></FormField><Actions onCancel={() => setProfileOpen(false)} pending={createProfileM.isPending} /></form>
      </Dialog>
      <Dialog open={postOpen} onClose={() => setPostOpen(false)} title="ثبت حسابداری فاکتور" size="lg">
        <form className="grid gap-3 sm:grid-cols-2" onSubmit={postForm.handleSubmit((v) => postM.mutate(v))}>
          <FormField label="شناسه سند مبدأ" error={postForm.formState.errors.source_document_id?.message}><Input dir="ltr" {...postForm.register("source_document_id")} /></FormField>
          <FormField label="پروفایل"><Select {...postForm.register("profile_id")}><option value="">پروفایل پیش‌فرض</option>{(profilesQ.data ?? []).map((p) => <option key={p.id} value={p.id}>{p.name}</option>)}</Select></FormField>
          <FormField label="مبلغ کل"><MoneyInput {...postForm.register("total_amount")} /></FormField>
          <FormField label="تخفیف"><MoneyInput {...postForm.register("discount_amount")} /></FormField>
          <FormField label="مالیات"><MoneyInput {...postForm.register("tax_amount")} /></FormField>
          {preview ? <div className="sm:col-span-2 rounded-xl bg-[var(--surface-muted)] p-3 text-sm">تراز: {preview.is_balanced ? "بله" : "خیر"} — بدهکار: {formatMoney(preview.total_debit)} — بستانکار: {formatMoney(preview.total_credit)}</div> : null}
          <div className="flex justify-end gap-2 sm:col-span-2"><Button type="button" variant="outline" disabled={previewM.isPending} onClick={postForm.handleSubmit((v) => previewM.mutate(v))}>پیش‌نمایش</Button><Button type="submit" disabled={postM.isPending}>ثبت نهایی</Button></div>
        </form>
      </Dialog>
    </div>
  );
}

type DocumentForm = ReturnType<typeof useForm<z.infer<typeof documentSchema>>>;
type DocumentMutation = ReturnType<typeof useMutation<unknown, Error, z.infer<typeof documentSchema>>>;

function DocumentDialog({
  open,
  onClose,
  title,
  form,
  mutation,
  partyModule,
}: {
  open: boolean;
  onClose: () => void;
  title: string;
  form: DocumentForm;
  mutation: DocumentMutation;
  partyModule?: string;
}) {
  return (
    <Dialog open={open} onClose={onClose} title={title} size="lg">
      <form
        className="grid gap-3 sm:grid-cols-2"
        onSubmit={form.handleSubmit((v) =>
          mutation.mutate({ ...v, amount: parseMoneyInput(v.amount) || "0" })
        )}
      >
        <FormField label="شماره" error={form.formState.errors.number?.message}>
          <Input {...form.register("number")} />
        </FormField>
        <FormField label="تاریخ" error={form.formState.errors.doc_date?.message}>
          <Controller
            control={form.control}
            name="doc_date"
            render={({ field }) => <DatePicker {...field} />}
          />
        </FormField>
        <FormField label="طرف حساب">
          <PartyCombobox
            module={partyModule}
            valueName={form.watch("party_name") || undefined}
            onChange={(party) => {
              form.setValue("party_name", party?.name || "");
              form.setValue("party_id", party?.id || "");
            }}
          />
        </FormField>
        <FormField label="مبلغ">
          <MoneyInput {...form.register("amount")} />
        </FormField>
        <div className="sm:col-span-2">
          <FormField label="توضیح">
            <Input {...form.register("description")} />
          </FormField>
        </div>
        <Actions onCancel={onClose} pending={mutation.isPending} />
      </form>
    </Dialog>
  );
}

const purchasePostSchema = z.object({ source_document_id: requiredText, amount: requiredText, profile_id: z.string() });

export function PurchaseGoodsReceiptPage() {
  const { tenantId } = useTenantId();
  const qc = useQueryClient();
  const [createOpen, setCreateOpen] = useState(false);
  const [postOpen, setPostOpen] = useState(false);
  const [preview, setPreview] = useState<{ is_balanced: boolean; total_debit: string } | null>(null);
  const docForm = useForm<z.infer<typeof documentSchema>>({ resolver: zodResolver(documentSchema), defaultValues: { number: "", doc_date: today(), party_name: "", amount: "0", description: "" } });
  const postForm = useForm<z.infer<typeof purchasePostSchema>>({ resolver: zodResolver(purchasePostSchema), defaultValues: { source_document_id: "", amount: "0", profile_id: "" } });
  const docsQ = useQuery({ queryKey: ["accounting", tenantId, "ops-docs", "purchase", "goods_receipt"], queryFn: () => accountingApi.ops.listDocuments(tenantId!, "purchase", "goods_receipt"), enabled: !!tenantId });
  const profilesQ = useQuery({ queryKey: ["accounting", tenantId, "purchase-profiles"], queryFn: () => accountingApi.purchaseInventory.listProfiles(tenantId!), enabled: !!tenantId });
  const createM = useMutation({
    mutationFn: (v: z.infer<typeof documentSchema>) => accountingApi.ops.createDocument(tenantId!, { module: "purchase", doc_type: "goods_receipt", status: "draft", ...v }),
    onSuccess: async () => { toast.success("رسید کالا ثبت شد"); setCreateOpen(false); docForm.reset(); await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "ops-docs", "purchase", "goods_receipt"] }); },
    onError: (e: Error) => toast.error(e.message),
  });
  const previewM = useMutation({
    mutationFn: (v: z.infer<typeof purchasePostSchema>) => accountingApi.purchaseInventory.previewGoodsReceipt(tenantId!, { ...v, profile_id: v.profile_id || undefined }),
    onSuccess: (data) => { setPreview(data); toast.success("پیش‌نمایش آماده شد"); },
    onError: (e: Error) => toast.error(e.message),
  });
  const postM = useMutation({
    mutationFn: (v: z.infer<typeof purchasePostSchema>) => accountingApi.purchaseInventory.postGoodsReceipt(tenantId!, { ...v, profile_id: v.profile_id || undefined }),
    onSuccess: () => { toast.success("رسید به حسابداری ارسال شد"); setPostOpen(false); setPreview(null); },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || docsQ.isLoading || profilesQ.isLoading) return <LoadingState />;
  if (docsQ.error || profilesQ.error) return <ErrorState message={(docsQ.error || profilesQ.error)!.message} onRetry={() => { docsQ.refetch(); profilesQ.refetch(); }} />;
  const openPosting = (r: Record<string, unknown>) => { postForm.reset({ source_document_id: String(r.id), amount: String(r.amount || "0"), profile_id: "" }); setPreview(null); setPostOpen(true); };
  return (
    <div>
      <PageHeader title="رسید کالا" description="ثبت رسید عملیاتی و ارسال آن به حسابداری خرید و انبار." actions={<Button onClick={() => setCreateOpen(true)}><Plus className="h-4 w-4" />رسید جدید</Button>} />
      <DataTable
        columns={[
          { key: "number", header: "شماره" }, { key: "doc_date", header: "تاریخ", render: (r) => <JalaliDateText value={String(r.doc_date)} /> },
          { key: "party_name", header: "تأمین‌کننده" }, { key: "amount", header: "مبلغ", render: (r) => formatMoney(String(r.amount)) },
          { key: "status", header: "وضعیت", render: (r) => <Badge>{String(r.status)}</Badge> },
          { key: "actions", header: "عملیات", render: (r) => <Button size="sm" variant="outline" onClick={() => openPosting(r)}>ثبت حسابداری</Button> },
        ]}
        rows={docsQ.data as unknown as Record<string, unknown>[]}
        empty={
          <EmptyState
            title="رسید کالایی ثبت نشده"
            description="برای شروع، رسید جدید ثبت کنید."
            action={
              <Button type="button" onClick={() => setCreateOpen(true)}>
                <Plus className="h-4 w-4" />
                رسید جدید
              </Button>
            }
          />
        }
      />
      <DocumentDialog open={createOpen} onClose={() => setCreateOpen(false)} title="ثبت رسید کالا" form={docForm} mutation={createM} partyModule="purchase" />
      <Dialog open={postOpen} onClose={() => setPostOpen(false)} title="ثبت حسابداری رسید کالا">
        <form className="grid gap-3" onSubmit={postForm.handleSubmit((v) => postM.mutate(v))}>
          <FormField label="شناسه سند مبدأ"><Input dir="ltr" {...postForm.register("source_document_id")} /></FormField>
          <FormField label="مبلغ"><MoneyInput {...postForm.register("amount")} /></FormField>
          <FormField label="پروفایل"><Select {...postForm.register("profile_id")}><option value="">پروفایل پیش‌فرض</option>{(profilesQ.data ?? []).map((p) => <option key={p.id} value={p.id}>{p.name}</option>)}</Select></FormField>
          {preview ? <div className="rounded-xl bg-[var(--surface-muted)] p-3 text-sm">تراز: {preview.is_balanced ? "بله" : "خیر"} — بدهکار: {formatMoney(preview.total_debit)}</div> : null}
          <div className="flex justify-end gap-2"><Button type="button" variant="outline" onClick={postForm.handleSubmit((v) => previewM.mutate(v))} disabled={previewM.isPending}>پیش‌نمایش</Button><Button type="submit" disabled={postM.isPending}>ثبت نهایی</Button></div>
        </form>
      </Dialog>
    </div>
  );
}

const valuationSchema = z.object({ item_id: requiredText, quantity: requiredText, unit_cost: requiredText, warehouse_id: z.string() });

export function InventoryValuationPage() {
  const { tenantId } = useTenantId();
  const [result, setResult] = useState<string | null>(null);
  const form = useForm<z.infer<typeof valuationSchema>>({ resolver: zodResolver(valuationSchema), defaultValues: { item_id: "", quantity: "0", unit_cost: "0", warehouse_id: "" } });
  const itemsQ = useQuery({ queryKey: ["accounting", tenantId, "ops-items"], queryFn: () => accountingApi.ops.listItems(tenantId!), enabled: !!tenantId });
  const warehousesQ = useQuery({ queryKey: ["accounting", tenantId, "ops-warehouses"], queryFn: () => accountingApi.ops.listWarehouses(tenantId!), enabled: !!tenantId });
  const valuationM = useMutation({
    mutationFn: (v: z.infer<typeof valuationSchema>) => accountingApi.purchaseInventory.valuation(tenantId!, { ...v, warehouse_id: v.warehouse_id || undefined }),
    onSuccess: (data) => { setResult(data.total_value); toast.success("ارزش‌گذاری ثبت شد"); },
    onError: (e: Error) => toast.error(e.message),
  });
  if (!tenantId || itemsQ.isLoading || warehousesQ.isLoading) return <LoadingState />;
  if (itemsQ.error || warehousesQ.error) return <ErrorState message={(itemsQ.error || warehousesQ.error)!.message} onRetry={() => { itemsQ.refetch(); warehousesQ.refetch(); }} />;
  return (
    <div>
      <PageHeader title="ارزش‌گذاری موجودی" description="محاسبه و ثبت ارزش موجودی بر اساس قلم، تعداد و بهای واحد." />
      <Card className="mb-6">
        <CardHeader><CardTitle>ثبت ارزش‌گذاری</CardTitle></CardHeader>
        <CardContent>
          <form className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4" onSubmit={form.handleSubmit((v) => valuationM.mutate(v))}>
            <FormField label="کالا"><Select {...form.register("item_id")}><option value="">انتخاب…</option>{(itemsQ.data ?? []).map((i) => <option key={i.id} value={i.id}>{i.code} — {i.name}</option>)}</Select></FormField>
            <FormField label="تعداد"><Input {...form.register("quantity")} /></FormField>
            <FormField label="بهای واحد"><MoneyInput {...form.register("unit_cost")} /></FormField>
            <FormField label="انبار (اختیاری)"><Select {...form.register("warehouse_id")}><option value="">بدون انبار</option>{(warehousesQ.data ?? []).map((w) => <option key={w.id} value={w.id}>{w.name}</option>)}</Select></FormField>
            <div className="flex items-end gap-3 lg:col-span-4"><Button type="submit" disabled={valuationM.isPending}>محاسبه و ثبت</Button>{result ? <span className="text-sm text-secondary">ارزش کل: {formatMoney(result)}</span> : null}</div>
          </form>
        </CardContent>
      </Card>
      <DataTable
        columns={[{ key: "code", header: "کد" }, { key: "name", header: "نام" }, { key: "unit", header: "واحد" }, { key: "quantity_on_hand", header: "موجودی" }, { key: "unit_cost", header: "بهای واحد", render: (r) => formatMoney(String(r.unit_cost)) }]}
        rows={itemsQ.data as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="کالایی تعریف نشده" />}
      />
    </div>
  );
}

export function MonitoringHealthPage() {
  const { tenantId } = useTenantId();
  const healthQ = useQuery({ queryKey: ["accounting", "health"], queryFn: () => accountingApi.health() });
  const setupQ = useQuery({ queryKey: ["accounting", tenantId, "setup-status"], queryFn: () => accountingApi.setup.status(tenantId!), enabled: !!tenantId });
  if (!tenantId || healthQ.isLoading || setupQ.isLoading) return <LoadingState />;
  if (healthQ.error || setupQ.error) return <ErrorState message={(healthQ.error || setupQ.error)!.message} onRetry={() => { healthQ.refetch(); setupQ.refetch(); }} />;
  return (
    <div>
      <PageHeader title="وضعیت سرویس حسابداری" description="سلامت API و میزان تکمیل پیکربندی مستأجر." />
      <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
        <StatCard label="وضعیت سرویس" value={healthQ.data!.status} hint={healthQ.data!.service} />
        <StatCard label="نسخه" value={healthQ.data!.version} />
        <StatCard label="پیشرفت راه‌اندازی" value={`${setupQ.data!.percent}%`} hint={`${setupQ.data!.completed_steps} از ${setupQ.data!.total_steps} مرحله`} />
        <StatCard label="آمادگی پایه" value={setupQ.data!.has_chart && setupQ.data!.has_fiscal_period ? "آماده" : "نیازمند تکمیل"} />
      </div>
    </div>
  );
}

export function AssetSchedulePage() {
  const { tenantId } = useTenantId();
  const [selectedName, setSelectedName] = useState("");
  const [schedule, setSchedule] = useState<Record<string, unknown>[] | null>(null);
  const assetsQ = useQuery({ queryKey: ["accounting", tenantId, "assets"], queryFn: () => accountingApi.assets.list(tenantId!), enabled: !!tenantId });
  const scheduleM = useMutation({
    mutationFn: (id: string) => accountingApi.assets.schedule(tenantId!, id),
    onSuccess: (data) => setSchedule(data.schedule as Record<string, unknown>[]),
    onError: (e: Error) => toast.error(e.message),
  });
  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> },
          { key: "actions", header: "عملیات", render: (r) => <Button size="sm" variant="outline" disabled={scheduleM.isPending} onClick={() => { setSelectedName(String(r.name)); scheduleM.mutate(String(r.id)); }}>مشاهده برنامه</Button> },
        ]}
        rows={assetsQ.data as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="دارایی ثبت نشده" />}
      />
      <Dialog open={schedule !== null} onClose={() => setSchedule(null)} title={`برنامه استهلاک ${selectedName}`} size="lg">
        <DataTable
          columns={[
            { key: "period", header: "دوره" },
            { key: "amount", header: "استهلاک", render: (r) => formatMoney(String(r.amount ?? "0")) },
            { key: "book_value_after", header: "ارزش دفتری پایان دوره", render: (r) => formatMoney(String(r.book_value_after ?? "0")) },
          ]}
          rows={schedule ?? []}
          empty={<EmptyState title="برنامه‌ای محاسبه نشده" />}
        />
      </Dialog>
    </div>
  );
}
