"use client";

import { useMemo, useState, Suspense } from "react";
import { useSearchParams } from "next/navigation";
import { useMutation, useQuery } from "@tanstack/react-query";
import { toast } from "sonner";
import { accountingApi } from "@/lib/accounting-api";
import { useTenantId } from "@/hooks/useTenantId";
import { formatMoney } from "@/lib/utils";
import {
  PageHeader,
  Button,
  LoadingState,
  ErrorState,
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  Badge,
  Select,
  FormField,
  DataTable,
  EmptyState,
  StatCard,
} from "@/components/ds";

type EngineKind = "trial-balance" | "balance-sheet" | "income-statement";
type LedgerReportKind =
  | "subsidiary"
  | "detail"
  | "analytical"
  | "cash-flow"
  | "equity";

const ENGINE_LABELS: Record<EngineKind, string> = {
  "trial-balance": "تراز آزمایشی",
  "balance-sheet": "ترازنامه",
  "income-statement": "سود و زیان",
};

const LEDGER_REPORT_META: Record<
  LedgerReportKind,
  { title: string; description: string; needsAccount?: boolean }
> = {
  subsidiary: {
    title: "گزارش معین",
    description: "مانده و گردش حساب‌های سطح معین بر اساس دفتر و اسناد ثبت‌شده.",
    needsAccount: true,
  },
  detail: {
    title: "گزارش تفصیلی",
    description: "مانده و گردش حساب‌های سطح تفصیلی بر اساس دفتر و اسناد ثبت‌شده.",
    needsAccount: true,
  },
  analytical: {
    title: "گزارش تحلیلی",
    description: "تجمیع مانده‌ها بر اساس نوع و دسته حساب از داده واقعی دفتر.",
  },
  "cash-flow": {
    title: "جریان وجوه نقد",
    description: "گردش حساب‌های نقدی/بانکی از مانده و اسناد ثبت‌شده.",
  },
  equity: {
    title: "تغییرات حقوق صاحبان سهام",
    description: "مانده و گردش حساب‌های حقوق صاحبان سهام در دوره انتخابی.",
  },
};

const FIELD_LABELS: Record<string, string> = {
  total_debit: "جمع بدهکار",
  total_credit: "جمع بستانکار",
  difference: "اختلاف",
  is_balanced: "متوازن",
  total_assets: "جمع دارایی‌ها",
  account_count: "تعداد حساب",
  total_revenue: "جمع درآمد",
  total_expense: "جمع هزینه",
  net: "خالص",
  net_cash_change: "تغییر خالص نقد",
  inflows: "ورودی‌ها",
  outflows: "خروجی‌ها",
};

type BalanceRow = {
  account_id: string;
  account_code: string;
  account_name: string;
  account_type?: string;
  account_category?: string;
  level?: number;
  opening_balance: string;
  debit_total: string;
  credit_total: string;
  closing_balance: string;
};

type StatementLine = {
  id: string;
  entry_date: string;
  description?: string | null;
  debit: string;
  credit: string;
  running_balance: string;
  entry_number?: string;
};

type LedgerReportData = {
  mode?: string;
  level_mode?: string;
  account?: { id: string; code: string; name: string; level: number };
  rows?: BalanceRow[];
  lines?: StatementLine[];
  totals?: Record<string, string | number>;
  by_type?: Array<Record<string, string | number>>;
  by_category?: Array<Record<string, string | number>>;
  net_cash_change?: string;
  inflows?: string;
  outflows?: string;
};

function parseReportData(data: unknown): Record<string, unknown> | null {
  if (!data) return null;
  if (typeof data === "string") {
    try {
      return JSON.parse(data) as Record<string, unknown>;
    } catch {
      return { raw: data };
    }
  }
  if (typeof data === "object" && !Array.isArray(data)) {
    return data as Record<string, unknown>;
  }
  return { value: data };
}

function formatCellValue(key: string, value: unknown): React.ReactNode {
  if (value === null || value === undefined) return "—";
  if (typeof value === "boolean") return value ? "بله" : "خیر";
  if (
    key.includes("total") ||
    key.includes("difference") ||
    key.includes("balance") ||
    key === "net" ||
    key.includes("amount") ||
    key.includes("inflow") ||
    key.includes("outflow") ||
    key.includes("change")
  ) {
    return formatMoney(String(value));
  }
  return String(value);
}

const MONEY_COLS = [
  {
    key: "opening_balance",
    header: "مانده اول دوره",
    render: (r: Record<string, unknown>) => formatMoney(String(r.opening_balance ?? "0")),
  },
  {
    key: "debit_total",
    header: "بدهکار",
    render: (r: Record<string, unknown>) => formatMoney(String(r.debit_total ?? "0")),
  },
  {
    key: "credit_total",
    header: "بستانکار",
    render: (r: Record<string, unknown>) => formatMoney(String(r.credit_total ?? "0")),
  },
  {
    key: "closing_balance",
    header: "مانده پایان",
    render: (r: Record<string, unknown>) => formatMoney(String(r.closing_balance ?? "0")),
  },
];

function EngineReports({ initialKind }: { initialKind?: string }) {
  const { tenantId } = useTenantId();
  const [periodId, setPeriodId] = useState("");
  const [result, setResult] = useState<{
    kind: EngineKind;
    payload: { id: string; data: unknown };
  } | null>(null);

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

  const runM = useMutation({
    mutationFn: async (kind: EngineKind) => {
      if (!periodId) throw new Error("دوره مالی را انتخاب کنید");
      if (kind === "trial-balance") {
        const payload = await accountingApi.reporting.trialBalance(tenantId!, periodId);
        return { kind, payload };
      }
      if (kind === "balance-sheet") {
        const payload = await accountingApi.reporting.balanceSheet(tenantId!, periodId);
        return { kind, payload };
      }
      const payload = await accountingApi.reporting.incomeStatement(tenantId!, periodId);
      return { kind, payload };
    },
    onSuccess: (data) => {
      setResult(data);
      toast.success("گزارش تولید شد");
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const exportM = useMutation({
    mutationFn: (format: "json" | "csv") =>
      accountingApi.reporting.export(tenantId!, result!.payload.id, format),
    onSuccess: (data) => {
      toast.success(`خروجی ${data.format} ثبت شد`);
      if (data.file_path) toast.message(data.file_path);
      if (result) {
        const blob = new Blob([JSON.stringify(result.payload, null, 2)], {
          type: "application/json",
        });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = `report-${result.payload.id}.json`;
        a.click();
        URL.revokeObjectURL(url);
      }
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const parsed = useMemo(
    () => (result ? parseReportData(result.payload.data) : null),
    [result]
  );

  const tableRows = useMemo(() => {
    if (!parsed) return [];
    return Object.entries(parsed).map(([key, value]) => ({
      id: key,
      field: FIELD_LABELS[key] ?? key,
      value,
      rawKey: key,
    }));
  }, [parsed]);

  if (!tenantId || periodsQ.isLoading) return <LoadingState />;
  if (periodsQ.error) {
    return <ErrorState message={periodsQ.error.message} onRetry={() => periodsQ.refetch()} />;
  }

  const highlight =
    initialKind === "trial-balance" ||
    initialKind === "balance-sheet" ||
    initialKind === "income-statement"
      ? (initialKind as EngineKind)
      : null;

  return (
    <div>
      <PageHeader
        title="گزارش‌های مالی"
        description="تراز آزمایشی، ترازنامه و سود و زیان — از Report Engine."
      />

      <Card className="mb-6">
        <CardContent className="grid gap-4 pt-6 sm:grid-cols-[1fr_auto] sm:items-end">
          <FormField label="دوره مالی">
            <Select value={periodId} onChange={(e) => setPeriodId(e.target.value)}>
              <option value="">انتخاب دوره</option>
              {(periodsQ.data ?? []).map((p) => (
                <option key={p.id} value={p.id}>
                  {p.name}
                </option>
              ))}
            </Select>
          </FormField>
          <div className="flex flex-wrap gap-2">
            {(Object.keys(ENGINE_LABELS) as EngineKind[]).map((kind) => (
              <Button
                key={kind}
                type="button"
                variant={highlight === kind ? "default" : "outline"}
                disabled={runM.isPending || !periodId}
                onClick={() => runM.mutate(kind)}
              >
                {ENGINE_LABELS[kind]}
              </Button>
            ))}
          </div>
        </CardContent>
      </Card>

      {result ? (
        <Card>
          <CardHeader>
            <CardTitle className="flex flex-wrap items-center gap-2">
              {ENGINE_LABELS[result.kind]}
              <Badge tone="primary">زنده</Badge>
              <span className="text-xs font-normal text-[var(--muted)]" dir="ltr">
                ID: {result.payload.id}
              </span>
              <Button
                type="button"
                size="sm"
                variant="outline"
                className="ms-auto"
                disabled={exportM.isPending}
                onClick={() => exportM.mutate("json")}
              >
                خروجی / Export
              </Button>
            </CardTitle>
          </CardHeader>
          <CardContent className="space-y-4">
            {parsed && tableRows.length > 0 ? (
              <DataTable
                columns={[
                  { key: "field", header: "عنوان" },
                  {
                    key: "value",
                    header: "مقدار",
                    render: (r) => formatCellValue(String(r.rawKey), r.value),
                  },
                ]}
                rows={tableRows as unknown as Record<string, unknown>[]}
              />
            ) : (
              <EmptyState title="داده‌ای برای نمایش نیست" />
            )}
            <details className="rounded-xl border border-[var(--border)] bg-[var(--surface-muted)] p-3">
              <summary className="cursor-pointer text-sm font-medium text-secondary">JSON خام</summary>
              <pre
                className="mt-3 max-h-[320px] overflow-auto text-xs leading-relaxed text-secondary"
                dir="ltr"
              >
                {JSON.stringify(result.payload, null, 2)}
              </pre>
            </details>
          </CardContent>
        </Card>
      ) : (
        <p className="text-sm text-[var(--muted)]">یک دوره انتخاب کنید و گزارش را اجرا کنید.</p>
      )}
    </div>
  );
}

function LedgerReports({ kind }: { kind: LedgerReportKind }) {
  const meta = LEDGER_REPORT_META[kind];
  const { tenantId } = useTenantId();
  const [periodId, setPeriodId] = useState("");
  const [accountId, setAccountId] = useState("");
  const [result, setResult] = useState<{ id: string; data: LedgerReportData } | null>(null);

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

  const accountsQ = useQuery({
    queryKey: ["accounting", tenantId, "accounts", "report-picker", kind],
    queryFn: () => accountingApi.accounts.list(tenantId!, 1, 500),
    enabled: !!tenantId && !!meta.needsAccount,
  });

  const accountOptions = useMemo(() => {
    const accounts = accountsQ.data ?? [];
    if (kind === "subsidiary") {
      const level3 = accounts.filter((a) => a.level === 3);
      if (level3.length) return level3;
      return accounts.filter((a) => a.is_postable && !a.is_group && a.level <= 3);
    }
    if (kind === "detail") {
      const detail = accounts.filter((a) => a.level >= 4);
      if (detail.length) return detail;
      return accounts.filter((a) => a.is_postable && !a.is_group);
    }
    return accounts.filter((a) => a.is_postable && !a.is_group);
  }, [accountsQ.data, kind]);

  const runM = useMutation({
    mutationFn: async () => {
      if (!periodId) throw new Error("دوره مالی را انتخاب کنید");
      const account = accountId || undefined;
      if (kind === "subsidiary") {
        return accountingApi.reporting.subsidiaryLedger(tenantId!, periodId, account);
      }
      if (kind === "detail") {
        return accountingApi.reporting.detailLedger(tenantId!, periodId, account);
      }
      if (kind === "analytical") {
        return accountingApi.reporting.analytical(tenantId!, periodId);
      }
      if (kind === "cash-flow") {
        return accountingApi.reporting.cashFlow(tenantId!, periodId);
      }
      return accountingApi.reporting.equityStatement(tenantId!, periodId);
    },
    onSuccess: (payload) => {
      const data = (parseReportData(payload.data) ?? {}) as LedgerReportData;
      setResult({ id: payload.id, data });
      toast.success("گزارش از داده دفتر تولید شد");
    },
    onError: (e: Error) => toast.error(e.message),
  });

  if (!tenantId || periodsQ.isLoading) return <LoadingState />;
  if (periodsQ.error) {
    return <ErrorState message={periodsQ.error.message} onRetry={() => periodsQ.refetch()} />;
  }

  const rows = result?.data.rows ?? [];
  const lines = result?.data.lines ?? [];
  const totals = result?.data.totals ?? {};
  const byType = result?.data.by_type ?? [];
  const byCategory = result?.data.by_category ?? [];

  return (
    <div>
      <PageHeader title={meta.title} description={meta.description} />

      <Card className="mb-6">
        <CardContent className="grid gap-4 pt-6 sm:grid-cols-2 lg:grid-cols-[1fr_1fr_auto] lg:items-end">
          <FormField label="دوره مالی">
            <Select value={periodId} onChange={(e) => setPeriodId(e.target.value)}>
              <option value="">انتخاب دوره</option>
              {(periodsQ.data ?? []).map((p) => (
                <option key={p.id} value={p.id}>
                  {p.name} {p.is_current ? "(جاری)" : ""}
                </option>
              ))}
            </Select>
          </FormField>

          {meta.needsAccount ? (
            <FormField label="حساب (اختیاری — برای گردش جزئیات)">
              <Select value={accountId} onChange={(e) => setAccountId(e.target.value)}>
                <option value="">همه حساب‌های این سطح</option>
                {accountOptions.map((a) => (
                  <option key={a.id} value={a.id}>
                    {a.code} — {a.name}
                  </option>
                ))}
              </Select>
            </FormField>
          ) : (
            <div />
          )}

          <Button
            type="button"
            disabled={runM.isPending || !periodId}
            onClick={() => runM.mutate()}
          >
            {runM.isPending ? "در حال تولید…" : "اجرای گزارش"}
          </Button>
        </CardContent>
      </Card>

      {result ? (
        <div className="space-y-6">
          <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
            <StatCard
              label="مانده اول دوره"
              value={formatMoney(String(totals.opening_balance ?? "0"))}
            />
            <StatCard label="جمع بدهکار" value={formatMoney(String(totals.debit_total ?? "0"))} />
            <StatCard label="جمع بستانکار" value={formatMoney(String(totals.credit_total ?? "0"))} />
            <StatCard
              label="مانده پایان"
              value={formatMoney(String(totals.closing_balance ?? "0"))}
            />
          </div>

          {kind === "cash-flow" ? (
            <div className="grid gap-4 sm:grid-cols-3">
              <StatCard
                label="ورودی‌ها"
                value={formatMoney(String(result.data.inflows ?? totals.debit_total ?? "0"))}
              />
              <StatCard
                label="خروجی‌ها"
                value={formatMoney(String(result.data.outflows ?? totals.credit_total ?? "0"))}
              />
              <StatCard
                label="تغییر خالص نقد"
                value={formatMoney(String(result.data.net_cash_change ?? "0"))}
              />
            </div>
          ) : null}

          {result.data.account ? (
            <Card>
              <CardHeader>
                <CardTitle className="flex flex-wrap items-center gap-2 text-base">
                  گردش حساب
                  <Badge tone="primary">
                    {result.data.account.code} — {result.data.account.name}
                  </Badge>
                </CardTitle>
              </CardHeader>
              <CardContent>
                {lines.length ? (
                  <DataTable
                    columns={[
                      { key: "entry_date", header: "تاریخ" },
                      {
                        key: "entry_number",
                        header: "شماره",
                        render: (r) => String(r.entry_number ?? "—"),
                      },
                      {
                        key: "description",
                        header: "شرح",
                        render: (r) => String(r.description ?? "—"),
                      },
                      {
                        key: "debit",
                        header: "بدهکار",
                        render: (r) => formatMoney(String(r.debit ?? "0")),
                      },
                      {
                        key: "credit",
                        header: "بستانکار",
                        render: (r) => formatMoney(String(r.credit ?? "0")),
                      },
                      {
                        key: "running_balance",
                        header: "مانده جاری",
                        render: (r) => formatMoney(String(r.running_balance ?? "0")),
                      },
                    ]}
                    rows={lines as unknown as Record<string, unknown>[]}
                  />
                ) : (
                  <EmptyState
                    title="گردشی برای این حساب در دوره نیست"
                    description="اسناد ثبت‌شده (Posted) روی این حساب در این دوره یافت نشد."
                  />
                )}
              </CardContent>
            </Card>
          ) : null}

          {kind === "analytical" ? (
            <>
              <Card>
                <CardHeader>
                  <CardTitle>بر اساس نوع حساب</CardTitle>
                </CardHeader>
                <CardContent>
                  {byType.length ? (
                    <DataTable
                      columns={[
                        { key: "key", header: "نوع" },
                        {
                          key: "account_count",
                          header: "تعداد",
                          render: (r) => String(r.account_count ?? 0),
                        },
                        ...MONEY_COLS,
                      ]}
                      rows={byType as unknown as Record<string, unknown>[]}
                    />
                  ) : (
                    <EmptyState title="داده‌ای نیست" />
                  )}
                </CardContent>
              </Card>
              <Card>
                <CardHeader>
                  <CardTitle>بر اساس دسته حساب</CardTitle>
                </CardHeader>
                <CardContent>
                  {byCategory.length ? (
                    <DataTable
                      columns={[
                        { key: "key", header: "دسته" },
                        {
                          key: "account_count",
                          header: "تعداد",
                          render: (r) => String(r.account_count ?? 0),
                        },
                        ...MONEY_COLS,
                      ]}
                      rows={byCategory as unknown as Record<string, unknown>[]}
                    />
                  ) : (
                    <EmptyState title="داده‌ای نیست" />
                  )}
                </CardContent>
              </Card>
            </>
          ) : null}

          <Card>
            <CardHeader>
              <CardTitle className="flex flex-wrap items-center gap-2">
                {result.data.mode === "statement" ? "مانده حساب انتخاب‌شده" : "خلاصه مانده حساب‌ها"}
                <Badge tone="primary">زنده از دفتر</Badge>
                <span className="text-xs font-normal text-[var(--muted)]" dir="ltr">
                  ID: {result.id}
                </span>
              </CardTitle>
            </CardHeader>
            <CardContent>
              {rows.length ? (
                <DataTable
                  columns={[
                    {
                      key: "account_code",
                      header: "کد",
                      render: (r) => (
                        <span dir="ltr">{String(r.account_code ?? "")}</span>
                      ),
                    },
                    { key: "account_name", header: "نام حساب" },
                    {
                      key: "level",
                      header: "سطح",
                      render: (r) => String(r.level ?? "—"),
                    },
                    ...MONEY_COLS,
                  ]}
                  rows={rows as unknown as Record<string, unknown>[]}
                />
              ) : (
                <EmptyState
                  title="حسابی برای نمایش نیست"
                  description="حساب‌های این سطح را در درخت حساب‌ها تعریف کنید و اسناد را ثبت (Post) کنید."
                />
              )}
            </CardContent>
          </Card>
        </div>
      ) : (
        <p className="text-sm text-[var(--muted)]">
          دوره مالی را انتخاب کنید و گزارش را اجرا کنید. داده از مانده دفتر و اسناد ثبت‌شده خوانده می‌شود — نه فرم ساختگی.
        </p>
      )}
    </div>
  );
}

function ReportsRouter() {
  const sp = useSearchParams();
  const type = sp.get("type") || "";
  if (type in LEDGER_REPORT_META) {
    return <LedgerReports kind={type as LedgerReportKind} />;
  }
  return <EngineReports initialKind={type || undefined} />;
}

export default function ReportsPage() {
  return (
    <Suspense fallback={<LoadingState />}>
      <ReportsRouter />
    </Suspense>
  );
}
