import type { RecurringBillFrequency, RecurringBillStatus, RecurringBillType } from "@prisma/client";
import {
  createRecurringBillAction,
  deleteProjectScopedRecordAction,
  markBillOccurrencePaidAction,
  skipBillOccurrenceAction,
  updateRecurringBillAction
} from "@/app/actions";
import { AppShell } from "@/components/AppShell";
import { ConfirmSubmitButton } from "@/components/ConfirmSubmitButton";
import { DeleteButton } from "@/components/DeleteButton";
import { DocumentViewer } from "@/components/DocumentViewer";
import { EmptyState } from "@/components/EmptyState";
import { FundingFields } from "@/components/FundingFields";
import { PageHeader } from "@/components/PageHeader";
import { ReceiptUploader } from "@/components/ReceiptUploader";
import { ReceiptViewer } from "@/components/ReceiptViewer";
import { StatusMessage } from "@/components/StatusMessage";
import { SummaryCard } from "@/components/SummaryCard";
import { financialPhaseLabels } from "@/lib/finance";
import { currency, dateInput, shortDate } from "@/lib/format";
import { buildProjectMetrics, type ProjectDetail } from "@/lib/metrics";
import { getSelectedProject } from "@/lib/projects";
import {
  billTimingMessage,
  billTypeLabels,
  effectiveBillStatus,
  frequencyLabels,
  parseReminderDays,
  recurringBillStatusLabels,
  reminderOptions,
  startOfDay,
  statusTone
} from "@/lib/recurringBills";

type BillRecord = ProjectDetail["recurringBills"][number];
type BillOccurrence = ProjectDetail["billOccurrences"][number];

type BillFilters = {
  projectId?: string;
  vendor: string;
  category: string;
  billType: string;
  status: string;
  autopay: string;
  from: string;
  to: string;
  month: string;
  quick: string;
};

const billTypes = Object.keys(billTypeLabels) as RecurringBillType[];
const frequencies = Object.keys(frequencyLabels) as RecurringBillFrequency[];
const statuses = Object.keys(recurringBillStatusLabels) as RecurringBillStatus[];

function oneParam(params: Record<string, string | string[] | undefined>, key: string) {
  const value = params[key];
  return Array.isArray(value) ? value[0] ?? "" : value ?? "";
}

function parseBillFilters(params: Record<string, string | string[] | undefined>): BillFilters {
  return {
    projectId: oneParam(params, "projectId") || undefined,
    vendor: oneParam(params, "vendor"),
    category: oneParam(params, "category"),
    billType: oneParam(params, "billType"),
    status: oneParam(params, "status"),
    autopay: oneParam(params, "autopay"),
    from: oneParam(params, "from"),
    to: oneParam(params, "to"),
    month: oneParam(params, "month"),
    quick: oneParam(params, "quick")
  };
}

function dateFilter(value: string, endOfDay = false) {
  if (!value) return null;
  const date = new Date(`${value}T${endOfDay ? "23:59:59.999" : "00:00:00.000"}`);
  return Number.isNaN(date.getTime()) ? null : date;
}

function occurrenceStatus(occurrence: BillOccurrence) {
  return effectiveBillStatus({
    dueDate: occurrence.dueDate,
    lastDateToPay: occurrence.lastDateToPay,
    status: occurrence.status,
    gracePeriodDays: occurrence.recurringBill.gracePeriodDays
  });
}

function filterOccurrences(occurrences: BillOccurrence[], filters: BillFilters) {
  const today = startOfDay(new Date());
  const weekEnd = new Date(today);
  weekEnd.setDate(weekEnd.getDate() + 7);
  const monthStart = new Date(today.getFullYear(), today.getMonth(), 1);
  const monthEnd = new Date(today.getFullYear(), today.getMonth() + 1, 0);
  const from = dateFilter(filters.from);
  const to = dateFilter(filters.to, true);

  return occurrences.filter((occurrence) => {
    const bill = occurrence.recurringBill;
    const dueDate = startOfDay(occurrence.dueDate);
    const status = occurrenceStatus(occurrence);
    if (!filters.status && (status === "ARCHIVED" || bill.status === "ARCHIVED")) return false;
    if (filters.vendor && !bill.vendor?.toLowerCase().includes(filters.vendor.toLowerCase())) return false;
    if (filters.category && (occurrence.categoryId ?? bill.categoryId) !== filters.category) return false;
    if (filters.billType && bill.billType !== filters.billType) return false;
    if (filters.status && status !== filters.status) return false;
    if (filters.autopay === "yes" && !bill.autopay) return false;
    if (filters.autopay === "no" && bill.autopay) return false;
    if (filters.month && dueDate.toISOString().slice(0, 7) !== filters.month) return false;
    if (filters.quick === "week" && (dueDate < today || dueDate > weekEnd)) return false;
    if (filters.quick === "month" && (dueDate < monthStart || dueDate > monthEnd)) return false;
    if (filters.quick === "overdue" && status !== "OVERDUE") return false;
    if (from && dueDate < from) return false;
    if (to && dueDate > to) return false;
    return true;
  });
}

function selectedMonth(value: string) {
  if (value) {
    const date = new Date(`${value}-01T00:00:00`);
    if (!Number.isNaN(date.getTime())) return date;
  }
  const today = new Date();
  return new Date(today.getFullYear(), today.getMonth(), 1);
}

function calendarDays(month: Date) {
  const first = new Date(month.getFullYear(), month.getMonth(), 1);
  const start = new Date(first);
  start.setDate(first.getDate() - first.getDay());
  return Array.from({ length: 42 }, (_, index) => {
    const date = new Date(start);
    date.setDate(start.getDate() + index);
    return date;
  });
}

function BillFields({ project, bill }: { project: ProjectDetail; bill?: BillRecord | BillOccurrence["recurringBill"] }) {
  const selectedPartnerIds = new Set(bill?.splitPartnerIds?.split(",").filter(Boolean) ?? project.partners.filter((partner) => partner.active).map((partner) => partner.id));
  const reminderDays = new Set(parseReminderDays(bill?.reminderDays).map(String));
  const categories = project.categories.filter((category) =>
    ["OPERATING_EXPENSE", "PURCHASE_COST", "RENOVATION_EXPENSE"].includes(category.type)
  );

  return (
    <>
      <div className="grid gap-4 md:grid-cols-2">
        <label className="grid gap-2">
          <span className="label">Bill name</span>
          <input className="field" name="name" defaultValue={bill?.name ?? ""} required />
        </label>
        <label className="grid gap-2">
          <span className="label">Vendor / company</span>
          <input className="field" name="vendor" defaultValue={bill?.vendor ?? ""} />
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-3">
        <label className="grid gap-2">
          <span className="label">Bill type</span>
          <select className="field" name="billType" defaultValue={bill?.billType ?? "OTHER"}>
            {billTypes.map((type) => (
              <option key={type} value={type}>{billTypeLabels[type]}</option>
            ))}
          </select>
        </label>
        <label className="grid gap-2">
          <span className="label">Category</span>
          <select className="field" name="categoryId" defaultValue={bill?.categoryId ?? ""}>
            <option value="">Uncategorized</option>
            {categories.map((category) => (
              <option key={category.id} value={category.id}>{category.name}</option>
            ))}
          </select>
        </label>
        <label className="grid gap-2">
          <span className="label">Amount</span>
          <input className="field" name="amount" type="number" min="0" step="0.01" defaultValue={bill ? Number(bill.amount) : ""} required />
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-3">
        <label className="grid gap-2">
          <span className="label">Frequency</span>
          <select className="field" name="frequency" defaultValue={bill?.frequency ?? "MONTHLY"}>
            {frequencies.map((frequency) => (
              <option key={frequency} value={frequency}>{frequencyLabels[frequency]}</option>
            ))}
          </select>
        </label>
        <label className="grid gap-2">
          <span className="label">Custom interval days</span>
          <input className="field" name="customIntervalDays" type="number" min="1" defaultValue={bill?.customIntervalDays ?? ""} />
        </label>
        <label className="grid gap-2">
          <span className="label">Status</span>
          <select className="field" name="status" defaultValue={bill?.status ?? "UPCOMING"}>
            {statuses.map((status) => (
              <option key={status} value={status}>{recurringBillStatusLabels[status]}</option>
            ))}
          </select>
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-3">
        <label className="grid gap-2">
          <span className="label">Start date</span>
          <input className="field" name="startDate" type="date" defaultValue={dateInput(bill?.startDate ?? new Date())} required />
        </label>
        <label className="grid gap-2">
          <span className="label">End date optional</span>
          <input className="field" name="endDate" type="date" defaultValue={dateInput(bill?.endDate)} />
        </label>
        <label className="grid gap-2">
          <span className="label">Next due date</span>
          <input className="field" name="nextDueDate" type="date" defaultValue={dateInput(bill?.nextDueDate ?? new Date())} required />
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-3">
        <label className="grid gap-2">
          <span className="label">Last date to pay</span>
          <input className="field" name="lastDateToPay" type="date" defaultValue={dateInput(bill?.lastDateToPay)} />
        </label>
        <label className="grid gap-2">
          <span className="label">Grace period days</span>
          <input className="field" name="gracePeriodDays" type="number" min="0" defaultValue={bill?.gracePeriodDays ?? 0} />
        </label>
        <label className="grid gap-2">
          <span className="label">Payment method</span>
          <input className="field" name="paymentMethod" defaultValue={bill?.paymentMethod ?? ""} />
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-2">
        <label className="grid gap-2">
          <span className="label">Paid / handled by default</span>
          <select className="field" name="defaultPaidById" defaultValue={bill?.defaultPaidById ?? ""}>
            <option value="">Choose when paid</option>
            {project.partners.map((partner) => (
              <option key={partner.id} value={partner.id}>{partner.partner.name}</option>
            ))}
          </select>
        </label>
        <label className="grid gap-2">
          <span className="label">Related document</span>
          <select className="field" name="relatedDocumentId" defaultValue={bill?.relatedDocumentId ?? ""}>
            <option value="">None</option>
            {project.documents.map((document) => (
              <option key={document.id} value={document.id}>{document.title}</option>
            ))}
          </select>
        </label>
      </div>

      <label className="flex items-center gap-2 text-sm font-medium text-slate-700">
        <input className="h-4 w-4 rounded border-line" name="autopay" type="checkbox" defaultChecked={bill?.autopay ?? false} />
        Autopay
      </label>

      <label className="grid gap-2">
        <span className="label">Split method</span>
        <select className="field" name="splitMethod" defaultValue={bill?.splitMethod ?? "EQUAL"}>
          <option value="EQUAL">Equal split</option>
          <option value="OWNERSHIP">Ownership percentage</option>
          <option value="PERSONAL">Personal expense</option>
        </select>
      </label>

      <div className="rounded-md border border-line p-3">
        <p className="label mb-3">Split between partners</p>
        <div className="grid gap-2 md:grid-cols-2">
          {project.partners.map((partner) => (
            <label key={partner.id} className="flex items-center gap-2 text-sm font-medium text-slate-700">
              <input className="h-4 w-4 rounded border-line" name="splitPartnerIds" type="checkbox" value={partner.id} defaultChecked={selectedPartnerIds.has(partner.id)} />
              {partner.partner.name}
            </label>
          ))}
        </div>
      </div>

      <div className="rounded-md border border-line p-3">
        <p className="label mb-3">Reminder settings</p>
        <div className="grid gap-2 md:grid-cols-2">
          {reminderOptions.map((option) => (
            <label key={option.value} className="flex items-center gap-2 text-sm font-medium text-slate-700">
              <input className="h-4 w-4 rounded border-line" name="reminderDays" type="checkbox" value={option.value} defaultChecked={reminderDays.has(option.value)} />
              {option.label}
            </label>
          ))}
        </div>
      </div>

      <label className="grid gap-2">
        <span className="label">Notes</span>
        <textarea className="field min-h-20" name="notes" defaultValue={bill?.notes ?? ""} />
      </label>
    </>
  );
}

function MarkPaidForm({ project, occurrence }: { project: ProjectDetail; occurrence: BillOccurrence }) {
  const bill = occurrence.recurringBill;
  const partnerOptions = project.partners.map((partner) => ({ id: partner.id, name: partner.partner.name }));
  const accountOptions = project.projectAccounts.map((account) => ({
    id: account.id,
    accountName: account.accountName,
    active: account.active
  }));
  return (
    <form action={markBillOccurrencePaidAction} className="mt-3 grid min-w-[380px] gap-3">
      <input type="hidden" name="projectId" value={project.id} />
      <input type="hidden" name="occurrenceId" value={occurrence.id} />
      <label className="grid gap-2">
        <span className="label">Payment date</span>
        <input className="field" name="paidDate" type="date" defaultValue={dateInput(new Date())} required />
      </label>
      <label className="grid gap-2">
        <span className="label">Amount paid</span>
        <input className="field" name="paidAmount" type="number" min="0" step="0.01" defaultValue={Number(occurrence.amount)} required />
      </label>
      <label className="grid gap-2">
        <span className="label">Payment method</span>
        <input className="field" name="paymentMethod" defaultValue={occurrence.paymentMethod ?? bill.paymentMethod ?? ""} />
      </label>
      <FundingFields
        partners={partnerOptions}
        accounts={accountOptions}
        defaultPaidById={occurrence.paidById ?? bill.defaultPaidById}
      />
      <label className="grid gap-2">
        <span className="label">Expense phase</span>
        <select className="field" name="expensePhase" defaultValue="RENTAL_OPERATION">
          <option value="RENTAL_OPERATION">{financialPhaseLabels.RENTAL_OPERATION}</option>
          <option value="POST_RENTAL_REPAIR_MAINTENANCE">{financialPhaseLabels.POST_RENTAL_REPAIR_MAINTENANCE}</option>
          <option value="ACQUISITION_CLOSING">{financialPhaseLabels.ACQUISITION_CLOSING}</option>
          <option value="RENOVATION_CAPITAL_IMPROVEMENT">{financialPhaseLabels.RENOVATION_CAPITAL_IMPROVEMENT}</option>
          <option value="OTHER">{financialPhaseLabels.OTHER}</option>
        </select>
      </label>
      <ReceiptUploader label="Receipt/proof" />
      <label className="flex items-center gap-2 text-sm font-medium text-slate-700">
        <input className="h-4 w-4 rounded border-line" name="createExpense" type="checkbox" defaultChecked />
        Create expense record
      </label>
      <label className="grid gap-2">
        <span className="label">Payment notes</span>
        <textarea className="field min-h-20" name="notes" defaultValue={occurrence.notes ?? ""} />
      </label>
      <ConfirmSubmitButton title="Review before saving" message="Mark this recurring bill occurrence as paid and save any related expense/receipt?" confirmLabel="Confirm Save">
        Mark as paid
      </ConfirmSubmitButton>
    </form>
  );
}

export default async function RecurringBillsPage({
  searchParams
}: {
  searchParams?: Promise<Record<string, string | string[] | undefined>>;
}) {
  const params = (await searchParams) ?? {};
  const filters = parseBillFilters(params);
  const { user, projects, project, permissions, projectRole } = await getSelectedProject(filters.projectId, "recurringBills.view");
  const canEdit = Boolean(permissions?.["recurringBills.create"] || permissions?.["recurringBills.edit"] || permissions?.["recurringBills.archive"] || permissions?.["recurringBills.delete"] || permissions?.["recurringBills.markPaid"]);

  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 adding recurring bills." href="/projects" actionLabel="Create project" />
      </AppShell>
    );
  }

  const metrics = buildProjectMetrics(project);
  const filteredOccurrences = filterOccurrences(project.billOccurrences, filters);
  const calendarMonth = selectedMonth(filters.month);
  const monthOccurrences = project.billOccurrences.filter(
    (occurrence) => startOfDay(occurrence.dueDate).toISOString().slice(0, 7) === dateInput(calendarMonth).slice(0, 7)
  );
  const categories = project.categories.filter((category) =>
    ["OPERATING_EXPENSE", "PURCHASE_COST", "RENOVATION_EXPENSE"].includes(category.type)
  );

  return (
    <AppShell projects={projects} selectedProjectId={project.id} username={user.name ?? user.username ?? user.email} role={projectRole ?? user.role} permissions={permissions}>
      <PageHeader
        title="Recurring Bills"
        description="Track future property bills, reminders, final payment dates, and paid occurrences separately from expenses."
      />
      <StatusMessage updated={params.updated} deleted={params.deleted} error={params.error} />

      <section className="grid gap-4 md:grid-cols-2 xl:grid-cols-5">
        <SummaryCard label="Due this week" value={String(metrics.billsDueThisWeek)} />
        <SummaryCard label="Due this month" value={String(metrics.billsDueThisMonth)} />
        <SummaryCard label="Overdue bills" value={String(metrics.overdueBills)} />
        <SummaryCard label="Autopay bills" value={String(metrics.autopayBills)} />
        <SummaryCard label="Expected this month" value={metrics.expectedBillsThisMonth} />
      </section>

      <section className="mt-6 grid gap-6 xl:grid-cols-[0.9fr_1.1fr]">
        {canEdit ? (
          <form action={createRecurringBillAction} className="panel grid gap-4 p-4">
            <h3 className="font-semibold text-ink">New Recurring Bill</h3>
            <input type="hidden" name="projectId" value={project.id} />
            <BillFields project={project} />
            <button className="btn-primary">Create bill and reminders</button>
          </form>
        ) : null}

        <div className="grid gap-4">
          <form className="panel grid gap-3 p-4 md:grid-cols-2" action="/recurring-bills">
            <input type="hidden" name="projectId" value={project.id} />
            <input className="field" name="vendor" placeholder="Vendor/company" defaultValue={filters.vendor} />
            <select className="field" name="category" defaultValue={filters.category}>
              <option value="">All categories</option>
              {categories.map((category) => (
                <option key={category.id} value={category.id}>{category.name}</option>
              ))}
            </select>
            <select className="field" name="billType" defaultValue={filters.billType}>
              <option value="">All bill types</option>
              {billTypes.map((type) => (
                <option key={type} value={type}>{billTypeLabels[type]}</option>
              ))}
            </select>
            <select className="field" name="status" defaultValue={filters.status}>
              <option value="">All active statuses</option>
              {statuses.map((status) => (
                <option key={status} value={status}>{recurringBillStatusLabels[status]}</option>
              ))}
            </select>
            <select className="field" name="autopay" defaultValue={filters.autopay}>
              <option value="">Autopay: any</option>
              <option value="yes">Autopay only</option>
              <option value="no">Manual pay only</option>
            </select>
            <select className="field" name="quick" defaultValue={filters.quick}>
              <option value="">Any due window</option>
              <option value="week">Due this week</option>
              <option value="month">Due this month</option>
              <option value="overdue">Overdue</option>
            </select>
            <input className="field" name="from" type="date" defaultValue={filters.from} title="From due date" />
            <input className="field" name="to" type="date" defaultValue={filters.to} title="To due date" />
            <input className="field" name="month" type="month" defaultValue={filters.month || dateInput(calendarMonth).slice(0, 7)} />
            <div className="flex flex-wrap gap-2 md:col-span-2">
              <button className="btn-secondary">Apply filters</button>
              <a className="btn-secondary" href={`/recurring-bills?projectId=${project.id}`}>Reset</a>
            </div>
          </form>

          <div className="panel overflow-hidden">
            <div className="border-b border-line px-4 py-3">
              <h3 className="font-semibold text-ink">Monthly Calendar</h3>
            </div>
            <div className="grid grid-cols-7 border-b border-line bg-slate-50 text-center text-xs font-semibold uppercase text-slate-500">
              {["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].map((day) => (
                <div key={day} className="border-r border-line px-2 py-2 last:border-r-0">{day}</div>
              ))}
            </div>
            <div className="grid grid-cols-7">
              {calendarDays(calendarMonth).map((day) => {
                const dayKey = dateInput(day);
                const dayOccurrences = monthOccurrences.filter((occurrence) => dateInput(occurrence.dueDate) === dayKey);
                const muted = day.getMonth() !== calendarMonth.getMonth();
                return (
                  <div key={dayKey} className={`min-h-24 border-b border-r border-line p-2 text-xs last:border-r-0 ${muted ? "bg-slate-50 text-slate-400" : "bg-white"}`}>
                    <p className="font-semibold">{day.getDate()}</p>
                    <div className="mt-1 grid gap-1">
                      {dayOccurrences.slice(0, 3).map((occurrence) => {
                        const status = occurrenceStatus(occurrence);
                        return (
                          <span key={occurrence.id} className={`rounded-md px-1.5 py-1 font-medium ${statusTone(status)}`}>
                            {occurrence.recurringBill.name}
                          </span>
                        );
                      })}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      </section>

      <section className="panel mt-6 overflow-hidden">
        <div className="flex flex-col gap-2 border-b border-line px-4 py-3 md:flex-row md:items-center md:justify-between">
          <h3 className="font-semibold text-ink">Bill Occurrences</h3>
          <p className="text-sm text-slate-500">{filteredOccurrences.length} shown</p>
        </div>
        <div className="overflow-x-auto">
          <table className="w-full min-w-[1460px]">
            <thead className="table-head">
              <tr>
                <th className="px-3 py-2">Bill</th>
                <th className="px-3 py-2">Vendor</th>
                <th className="px-3 py-2">Type</th>
                <th className="px-3 py-2">Due date</th>
                <th className="px-3 py-2">Last date</th>
                <th className="px-3 py-2">Amount</th>
                <th className="px-3 py-2">Status</th>
                <th className="px-3 py-2">Autopay</th>
                <th className="px-3 py-2">Document</th>
                <th className="px-3 py-2">Receipt</th>
                {canEdit ? <th className="px-3 py-2">Actions</th> : null}
              </tr>
            </thead>
            <tbody>
              {filteredOccurrences.map((occurrence) => {
                const bill = occurrence.recurringBill;
                const status = occurrenceStatus(occurrence);
                return (
                  <tr key={occurrence.id}>
                    <td className="table-cell">
                      <div className="font-medium text-ink">{bill.name}</div>
                      <div className="text-xs text-slate-500">{billTimingMessage({
                        dueDate: occurrence.dueDate,
                        lastDateToPay: occurrence.lastDateToPay,
                        status: occurrence.status,
                        gracePeriodDays: bill.gracePeriodDays
                      })}</div>
                    </td>
                    <td className="table-cell">{bill.vendor ?? "-"}</td>
                    <td className="table-cell">{billTypeLabels[bill.billType]}</td>
                    <td className="table-cell">{shortDate(occurrence.dueDate)}</td>
                    <td className="table-cell">{shortDate(occurrence.lastDateToPay)}</td>
                    <td className="table-cell font-semibold text-ink">{currency(Number(occurrence.amount))}</td>
                    <td className="table-cell">
                      <span className={`inline-flex rounded-md px-2 py-1 text-xs font-semibold ${statusTone(status)}`}>
                        {recurringBillStatusLabels[status]}
                      </span>
                    </td>
                    <td className="table-cell">
                      <span className={`inline-flex rounded-md px-2 py-1 text-xs font-semibold ${bill.autopay ? "bg-blue-50 text-blue-700" : "bg-slate-100 text-slate-600"}`}>
                        {bill.autopay ? "Autopay" : "Manual"}
                      </span>
                    </td>
                    <td className="table-cell">
                      {bill.relatedDocument ? (
                        <DocumentViewer url={bill.relatedDocument.fileUrl} fileName={bill.relatedDocument.fileName} mimeType={bill.relatedDocument.fileMimeType} compact buttonLabel="View" />
                      ) : "-"}
                    </td>
                    <td className="table-cell">
                      <ReceiptViewer url={occurrence.receiptUrl} emptyLabel="No proof" compact />
                    </td>
                    {canEdit ? (
                      <td className="table-cell align-top">
                        <div className="flex flex-wrap gap-2">
                          {status !== "PAID" && status !== "SKIPPED" && status !== "ARCHIVED" ? (
                            <details className="action-modal">
                              <summary>Mark paid</summary>
                              <MarkPaidForm project={project} occurrence={occurrence} />
                            </details>
                          ) : null}
                          <details className="action-modal">
                            <summary>Edit bill</summary>
                            <form action={updateRecurringBillAction} className="mt-3 grid min-w-[420px] gap-3">
                              <input type="hidden" name="projectId" value={project.id} />
                              <input type="hidden" name="recurringBillId" value={bill.id} />
                              <BillFields project={project} bill={bill} />
                              <button className="btn-primary">Update bill</button>
                            </form>
                          </details>
                          {status !== "PAID" && status !== "SKIPPED" && status !== "ARCHIVED" ? (
                            <form action={skipBillOccurrenceAction}>
                              <input type="hidden" name="projectId" value={project.id} />
                              <input type="hidden" name="occurrenceId" value={occurrence.id} />
                              <button className="btn-secondary" title="Skip this occurrence">Skip</button>
                            </form>
                          ) : null}
                          <form action={deleteProjectScopedRecordAction}>
                            <input type="hidden" name="projectId" value={project.id} />
                            <input type="hidden" name="model" value="recurringBill" />
                            <input type="hidden" name="id" value={bill.id} />
                            <input type="hidden" name="returnTo" value="/recurring-bills" />
                            <DeleteButton label="Archive bill" message={`Archive ${bill.name}? Paid history stays visible in expenses and reports.`} />
                          </form>
                        </div>
                      </td>
                    ) : null}
                  </tr>
                );
              })}
            </tbody>
          </table>
          {filteredOccurrences.length === 0 ? (
            <div className="p-6 text-sm text-slate-600">No recurring bill occurrences match this filter.</div>
          ) : null}
        </div>
      </section>
    </AppShell>
  );
}
