import Link from "next/link";
import type { ReactNode } from "react";
import { AppShell } from "@/components/AppShell";
import { EmptyState } from "@/components/EmptyState";
import { ExpenseDetailPanel } from "@/components/ExpenseDetailPanel";
import { ExportOptions } from "@/components/ExportOptions";
import { PageHeader } from "@/components/PageHeader";
import { PaginationControls } from "@/components/PaginationControls";
import { ReceiptFilesButton } from "@/components/ReceiptFilesViewer";
import { SelectionToolbar } from "@/components/SelectionToolbar";
import { SummaryCard } from "@/components/SummaryCard";
import { TransactionTableRow } from "@/components/TransactionTableRow";
import { quickRange } from "@/lib/expenseFilters";
import { financialPhaseLabels } from "@/lib/finance";
import { fundingSourceLabels } from "@/lib/funding";
import { currency, formatDateOnlyIso, shortDate } from "@/lib/format";
import { workerSummaryMap } from "@/lib/labor";
import { firstParam, paginateItems, paginationFromParams } from "@/lib/pagination";
import { getSelectedProject } from "@/lib/projects";
import type { ProjectDetail } from "@/lib/metrics";

type TransactionRow = {
  id: string;
  sourceId: string;
  date: Date;
  projectName: string;
  type: string;
  phase: string;
  category: string;
  actor: string;
  fundingSource: string;
  description: string;
  amount: number;
  status: string;
  receiptUrl?: string | null;
  receiptName?: string | null;
  receiptFiles?: { id?: string; fileName?: string | null; fileUrl?: string | null; mimeType?: string | null }[];
  detail: ReactNode;
  actionHref: string;
};

const quickFilters = [
  ["today", "Today"],
  ["this-week", "This week"],
  ["this-month", "This month"],
  ["last-month", "Last month"],
  ["this-year", "This year"],
  ["all", "All time"]
] as const;

function dateKey(date: Date) {
  return formatDateOnlyIso(date);
}

function buildTransactions(project: ProjectDetail): TransactionRow[] {
  const rows: TransactionRow[] = [];
  const laborSummaries = workerSummaryMap(project);

  for (const expense of project.expenses) {
    rows.push({
      id: `expense:${expense.id}`,
      sourceId: expense.id,
      date: expense.date,
      projectName: project.name,
      type: expense.transactionKind === "LABOR_COST" ? "Labor Cost / Worker Payment" : "Expense / Cost",
      phase: financialPhaseLabels[expense.phase],
      category: expense.transactionKind === "LABOR_COST" ? "Labor Cost" : expense.category?.name ?? "Uncategorized",
      actor: expense.paidBy?.partner.name ?? "-",
      fundingSource: fundingSourceLabels[expense.fundingSourceType] ?? expense.fundingSourceType,
      description: expense.vendor ?? expense.description ?? expense.worker?.name ?? "Expense",
      amount: Number(expense.finalCost),
      status: "Active",
      receiptUrl: expense.receiptUrl,
      receiptName: expense.receiptFiles[0]?.fileName,
      receiptFiles: expense.receiptFiles,
      detail: <ExpenseDetailPanel expense={expense} workerSummary={expense.workerId ? laborSummaries[expense.workerId] : null} />,
      actionHref: `/expenses?projectId=${project.id}`
    });
  }

  for (const contribution of project.contributions) {
    rows.push({
      id: `contribution:${contribution.id}`,
      sourceId: contribution.id,
      date: contribution.date,
      projectName: project.name,
      type: "Partner Contribution",
      phase: financialPhaseLabels[contribution.phase],
      category: "Contribution",
      actor: contribution.partner.partner.name,
      fundingSource: contribution.projectAccount?.accountName ?? "Project capital",
      description: contribution.purpose ?? contribution.paymentMethod ?? "Contribution",
      amount: Number(contribution.amount),
      status: "Active",
      receiptUrl: contribution.proofUrl,
      detail: (
        <div className="grid gap-3 rounded-md border border-line bg-slate-50 p-3 text-sm md:grid-cols-2">
          <div><p className="label">Partner</p><p className="font-medium text-ink">{contribution.partner.partner.name}</p></div>
          <div><p className="label">Destination</p><p className="font-medium text-ink">{contribution.projectAccount?.accountName ?? "-"}</p></div>
          <div><p className="label">Method</p><p className="font-medium text-ink">{contribution.paymentMethod ?? "-"}</p></div>
          <div><p className="label">Notes</p><p className="font-medium text-ink">{contribution.notes ?? "-"}</p></div>
        </div>
      ),
      actionHref: `/contributions?projectId=${project.id}`
    });
  }

  for (const payment of project.rentPayments) {
    rows.push({
      id: `rent:${payment.id}`,
      sourceId: payment.id,
      date: payment.paymentDate ?? payment.month,
      projectName: project.name,
      type: "Rent Payment",
      phase: financialPhaseLabels[payment.phase],
      category: "Rent",
      actor: payment.tenant.name,
      fundingSource: payment.paymentMethod ?? "-",
      description: `${payment.tenant.name} rent ${formatDateOnlyIso(payment.month).slice(0, 7)}`,
      amount: Number(payment.rentPaid),
      status: payment.status,
      detail: (
        <div className="grid gap-3 rounded-md border border-line bg-slate-50 p-3 text-sm md:grid-cols-2">
          <div><p className="label">Rent Expected</p><p className="font-medium text-ink">{currency(Number(payment.rentExpected))}</p></div>
          <div><p className="label">Rent Paid</p><p className="font-medium text-ink">{currency(Number(payment.rentPaid))}</p></div>
          <div><p className="label">Balance Due</p><p className="font-medium text-ink">{currency(Number(payment.balanceDue))}</p></div>
          <div><p className="label">Notes</p><p className="font-medium text-ink">{payment.notes ?? "-"}</p></div>
        </div>
      ),
      actionHref: `/rent?projectId=${project.id}`
    });
  }

  for (const deposit of project.securityDeposits) {
    rows.push({
      id: `deposit:${deposit.id}`,
      sourceId: deposit.id,
      date: deposit.dateReturned ?? deposit.dateReceived ?? deposit.createdAt,
      projectName: project.name,
      type: "Security Deposit",
      phase: financialPhaseLabels[deposit.phase],
      category: "Security Deposit",
      actor: deposit.tenant.name,
      fundingSource: Number(deposit.amountReturned) > 0 ? "Returned" : "Received",
      description: deposit.reasonWithheld ?? `${deposit.tenant.name} deposit`,
      amount: Number(deposit.amountReceived) - Number(deposit.amountReturned),
      status: deposit.archived ? "Archived" : "Active",
      detail: (
        <div className="grid gap-3 rounded-md border border-line bg-slate-50 p-3 text-sm md:grid-cols-2">
          <div><p className="label">Received</p><p className="font-medium text-ink">{currency(Number(deposit.amountReceived))}</p></div>
          <div><p className="label">Returned</p><p className="font-medium text-ink">{currency(Number(deposit.amountReturned))}</p></div>
          <div><p className="label">Withheld</p><p className="font-medium text-ink">{currency(Number(deposit.amountWithheld))}</p></div>
          <div><p className="label">Notes</p><p className="font-medium text-ink">{deposit.notes ?? "-"}</p></div>
        </div>
      ),
      actionHref: `/security-deposits?projectId=${project.id}`
    });
  }

  for (const income of project.incomes) {
    rows.push({
      id: `income:${income.id}`,
      sourceId: income.id,
      date: income.date,
      projectName: project.name,
      type: "Other Income",
      phase: financialPhaseLabels[income.phase],
      category: income.category?.name ?? "Income",
      actor: "-",
      fundingSource: "Income",
      description: income.description ?? "Income",
      amount: Number(income.amount),
      status: income.archived ? "Archived" : "Active",
      detail: <div className="rounded-md border border-line bg-slate-50 p-3 text-sm">{income.notes ?? "No notes"}</div>,
      actionHref: `/profit-loss?projectId=${project.id}`
    });
  }

  for (const expense of project.operatingExpenses) {
    rows.push({
      id: `operating:${expense.id}`,
      sourceId: expense.id,
      date: expense.date,
      projectName: project.name,
      type: "Operating Expense",
      phase: "Rental Operation",
      category: expense.category?.name ?? "Operating Expense",
      actor: "-",
      fundingSource: "-",
      description: expense.vendor ?? expense.description ?? "Operating expense",
      amount: Number(expense.amount),
      status: expense.archived ? "Archived" : "Active",
      detail: <div className="rounded-md border border-line bg-slate-50 p-3 text-sm">{expense.notes ?? "No notes"}</div>,
      actionHref: `/profit-loss?projectId=${project.id}`
    });
  }

  for (const occurrence of project.billOccurrences.filter((item) => item.status === "PAID")) {
    rows.push({
      id: `bill:${occurrence.id}`,
      sourceId: occurrence.id,
      date: occurrence.paidDate ?? occurrence.dueDate,
      projectName: project.name,
      type: "Recurring Bill Payment",
      phase: occurrence.relatedExpense ? financialPhaseLabels[occurrence.relatedExpense.phase] : "Rental Operation",
      category: occurrence.category?.name ?? occurrence.recurringBill.category?.name ?? "Recurring Bill",
      actor: occurrence.paidBy?.partner.name ?? "-",
      fundingSource: occurrence.paymentMethod ?? "-",
      description: occurrence.recurringBill.name,
      amount: Number(occurrence.paidAmount ?? occurrence.amount),
      status: occurrence.status,
      receiptUrl: occurrence.receiptUrl,
      detail: (
        <div className="grid gap-3 rounded-md border border-line bg-slate-50 p-3 text-sm md:grid-cols-2">
          <div><p className="label">Due Date</p><p className="font-medium text-ink">{shortDate(occurrence.dueDate)}</p></div>
          <div><p className="label">Paid Date</p><p className="font-medium text-ink">{occurrence.paidDate ? shortDate(occurrence.paidDate) : "-"}</p></div>
          <div><p className="label">Payment Method</p><p className="font-medium text-ink">{occurrence.paymentMethod ?? "-"}</p></div>
          <div><p className="label">Notes</p><p className="font-medium text-ink">{occurrence.notes ?? "-"}</p></div>
        </div>
      ),
      actionHref: `/recurring-bills?projectId=${project.id}`
    });
  }

  return rows.sort((a, b) => b.date.getTime() - a.date.getTime());
}

export default async function TransactionsPage({
  searchParams
}: {
  searchParams?: Promise<Record<string, string | string[] | undefined>>;
}) {
  const params = (await searchParams) ?? {};
  const selected = firstParam(params.projectId);
  const { user, projects, project, permissions, projectRole } = await getSelectedProject(selected, "reports.view");

  if (!project) {
    return (
      <AppShell projects={projects} username={user.name ?? user.username ?? user.email} role={projectRole ?? user.role} permissions={permissions}>
        <EmptyState title="Create a project before viewing transactions." href="/projects" actionLabel="Create project" />
      </AppShell>
    );
  }

  const quick = quickRange(firstParam(params.quick));
  const filters = {
    type: firstParam(params.type) ?? "",
    phase: firstParam(params.phase) ?? "",
    category: firstParam(params.category) ?? "",
    fundingSource: firstParam(params.fundingSource) ?? "",
    search: (firstParam(params.search) ?? "").toLowerCase().trim(),
    from: firstParam(params.from) || quick.from || "",
    to: firstParam(params.to) || quick.to || ""
  };
  const rows = buildTransactions(project).filter((row) => {
    const rowDate = dateKey(row.date);
    const haystack = [row.type, row.phase, row.category, row.actor, row.fundingSource, row.description, row.status].join(" ").toLowerCase();
    return (
      (!filters.type || row.type === filters.type) &&
      (!filters.phase || row.phase === filters.phase) &&
      (!filters.category || row.category === filters.category) &&
      (!filters.fundingSource || row.fundingSource === filters.fundingSource) &&
      (!filters.from || rowDate >= filters.from) &&
      (!filters.to || rowDate <= filters.to) &&
      (!filters.search || haystack.includes(filters.search))
    );
  });
  const pagination = paginationFromParams(params, rows.length);
  const pagedRows = paginateItems(rows, pagination);
  const totalAmount = rows.reduce((sum, row) => sum + row.amount, 0);
  const transactionTypes = [...new Set(buildTransactions(project).map((row) => row.type))].sort();
  const categories = [...new Set(buildTransactions(project).map((row) => row.category))].sort();
  const fundingSources = [...new Set(buildTransactions(project).map((row) => row.fundingSource))].sort();
  const transactionExportParams = new URLSearchParams({ projectId: project.id });
  if (filters.type) transactionExportParams.set("type", filters.type);
  if (filters.phase) transactionExportParams.set("phase", filters.phase);
  if (filters.category) transactionExportParams.set("category", filters.category);
  if (filters.fundingSource) transactionExportParams.set("fundingSource", filters.fundingSource);
  if (firstParam(params.search)) transactionExportParams.set("search", firstParam(params.search) ?? "");
  if (filters.from) transactionExportParams.set("from", filters.from);
  if (filters.to) transactionExportParams.set("to", filters.to);

  const quickUrl = (quickValue: string) => {
    const search = new URLSearchParams();
    search.set("projectId", project.id);
    search.set("quick", quickValue);
    return `/transactions?${search.toString()}`;
  };

  return (
    <AppShell projects={projects} selectedProjectId={project.id} username={user.name ?? user.username ?? user.email} role={projectRole ?? user.role} permissions={permissions}>
      <PageHeader
        title="All Transactions"
        description="Review every money-related record together while keeping the specialized pages available."
        actions={<ExportOptions baseUrl={`/api/exports/transactions?${transactionExportParams.toString()}`} reportTitle="All Transactions Export" />}
      />

      <section className="grid gap-4 md:grid-cols-3">
        <SummaryCard label="Transactions" value={String(rows.length)} />
        <SummaryCard label="Total Amount" value={totalAmount} />
        <SummaryCard label="Project" value={project.name} />
      </section>

      <form className="panel mt-6 grid gap-3 p-4 md:grid-cols-4" action="/transactions">
        <input type="hidden" name="projectId" value={project.id} />
        <select className="field" name="type" defaultValue={filters.type}>
          <option value="">All transaction types</option>
          {transactionTypes.map((type) => <option key={type} value={type}>{type}</option>)}
        </select>
        <select className="field" name="category" defaultValue={filters.category}>
          <option value="">All categories</option>
          {categories.map((category) => <option key={category} value={category}>{category}</option>)}
        </select>
        <select className="field" name="fundingSource" defaultValue={filters.fundingSource}>
          <option value="">All funding sources</option>
          {fundingSources.map((source) => <option key={source} value={source}>{source}</option>)}
        </select>
        <input className="field" name="search" placeholder="Vendor, description, notes" defaultValue={firstParam(params.search) ?? ""} />
        <input className="field" name="from" type="date" defaultValue={filters.from} />
        <input className="field" name="to" type="date" defaultValue={filters.to} />
        <button className="btn-secondary md:col-span-2">Apply filters</button>
      </form>

      <div className="panel mt-4 p-4">
        <p className="label mb-3">Quick filters</p>
        <div className="flex flex-wrap gap-2">
          {quickFilters.map(([value, label]) => (
            <Link key={value} className="btn-secondary" href={quickUrl(value)}>{label}</Link>
          ))}
        </div>
      </div>

      <section className="panel mt-6 overflow-hidden">
        <div className="border-b border-line px-4 py-3">
          <h3 className="font-semibold text-ink">Transaction Records</h3>
        </div>
        <div className="overflow-x-auto">
          <SelectionToolbar totalRecords={rows.length}>
            <table className="w-full min-w-[980px]">
              <thead className="table-head">
                <tr>
                  <th className="px-3 py-2">Select</th>
                  <th className="px-3 py-2">Details</th>
                  <th className="px-3 py-2">Date</th>
                  <th className="px-3 py-2">Vendor / Name</th>
                  <th className="px-3 py-2">Category</th>
                  <th className="px-3 py-2">Paid By</th>
                  <th className="px-3 py-2">Final Price</th>
                  <th className="px-3 py-2">Project</th>
                  <th className="px-3 py-2">Actions</th>
                </tr>
              </thead>
              <tbody>
                {pagedRows.map((row) => (
                  <TransactionTableRow
                    key={row.id}
                    id={row.id}
                    selectLabel={`Select ${row.description}`}
                    date={shortDate(row.date)}
                    description={row.description}
                    category={row.category}
                    paidBy={row.actor}
                    amount={currency(row.amount)}
                    project={row.projectName}
                    detail={(
                      <div className="grid gap-4">
                        {row.type === "Expense / Cost" ? null : (
                          <div className="grid gap-3 rounded-md border border-line bg-white p-3 text-sm md:grid-cols-4">
                            <div><p className="label">Type</p><p className="mt-1 font-medium text-ink">{row.type}</p></div>
                            <div><p className="label">Phase</p><p className="mt-1 font-medium text-ink">{row.phase}</p></div>
                            <div><p className="label">Funding</p><p className="mt-1 font-medium text-ink">{row.fundingSource}</p></div>
                            <div><p className="label">Status</p><p className="mt-1 font-medium text-ink">{row.status}</p></div>
                          </div>
                        )}
                        {row.detail}
                      </div>
                    )}
                    actions={(
                      <div className="flex flex-wrap items-center gap-2">
                        <Link className="btn-secondary px-2 py-1 text-xs" href={row.actionHref}>View</Link>
                        <a className="btn-secondary px-2 py-1 text-xs" href={`/api/exports/transactions?projectId=${project.id}&scope=selected&selectedIds=${encodeURIComponent(row.id)}&format=xlsx&reportTitle=Single%20Transaction`}>
                          Export
                        </a>
                        <ReceiptFilesButton files={row.receiptFiles} legacyUrl={row.receiptUrl} legacyFileName={row.receiptName} emptyLabel="No Receipt" compact />
                      </div>
                    )}
                  />
                ))}
              </tbody>
            </table>
          </SelectionToolbar>
          <PaginationControls pagination={pagination} pathname="/transactions" params={params} />
          {pagedRows.length === 0 ? <div className="p-6 text-sm text-slate-600">No transactions match these filters.</div> : null}
        </div>
      </section>
    </AppShell>
  );
}
