import type { Column } from './components';
import type { ConfirmState } from './ConfirmDialog';
import type { Invoice, RecurringInvoice, RecurringStatus } from './shared';
import { useState } from 'react';
import { MoreHorizontal, Plus, Repeat, Trash2, X } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import {
  EmptyState,
  ErrorState,
  Field,
  Pagination,
  SearchBox,
  SectionShell,
  SimpleTable,
  StatusBadge,
} from './components';
import { ConfirmDialog } from './ConfirmDialog';
import { formatDate, formatMoney } from './format';
import { PAGE_SIZE, RECURRING_TABS, frequencyLabel } from './shared';
import { StatusTabs } from './components';
import { useListFilters } from './useInvoicesSection';
import { useCurrency, useResourceDetail, useResourceList, useResourceMutations } from './useInvoiceShelfData';

// Recurring invoices — a schedule, not a document.
//
// This is the one section whose detail pane is NOT a PDF, and it is not an omission: a recurring invoice has
// no unique_hash and no PDF route upstream, because there is nothing to render. What it has is a schedule and
// a list of the invoices that schedule has already generated, so that is what the pane shows.
//
// The schedule's `frequency` is a cron expression; frequencyLabel turns the ones upstream's own form can
// produce back into words and leaves anything else alone.

type Props = { onEdit: (id: number | 'new') => void };

export const RecurringListView = ({ onEdit }: Props) => {
  const { filters, patch, select, setPage, clearFilters } = useListFilters();
  const currency = useCurrency();
  const [selection, setSelection] = useState<Set<number>>(new Set());
  const [confirm, setConfirm] = useState<ConfirmState>(null);

  const { rows, meta, isLoading, error } = useResourceList<RecurringInvoice>('recurring-invoices', {
    page: filters.page,
    limit: PAGE_SIZE,
    search: filters.search || undefined,
    status: filters.status || undefined,
    customer_id: filters.customerId || undefined,
    orderByField: 'created_at',
    orderBy: 'desc',
  });

  const { remove, removeMany } = useResourceMutations('recurring-invoices', 'recurring invoices');

  const toggleRow = (id: number) =>
    setSelection((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });

  const allChecked = rows.length > 0 && rows.every((r) => selection.has(r.id));

  const columns: Column<RecurringInvoice>[] = [
    {
      key: 'check',
      label: '',
      width: '36px',
      render: (row) => (
        <span onClick={(e) => e.stopPropagation()} className="flex items-center">
          <Checkbox checked={selection.has(row.id)} onCheckedChange={() => toggleRow(row.id)} />
        </span>
      ),
    },
    {
      key: 'starts_at',
      label: 'Starts at',
      width: 'minmax(90px, 0.9fr)',
      render: (row) => formatDate(row.starts_at, row.formatted_starts_at),
    },
    {
      key: 'customer',
      label: 'Customer',
      width: 'minmax(140px, 1.6fr)',
      render: (row) => (
        <div className="min-w-0">
          <div className="truncate">{row.customer?.name ?? '—'}</div>
          {row.customer?.contact_name && (
            <div className="truncate text-[10px] text-muted-foreground">{row.customer.contact_name}</div>
          )}
        </div>
      ),
    },
    {
      key: 'frequency',
      label: 'Frequency',
      width: 'minmax(100px, 1.1fr)',
      render: (row) => <span className="truncate">{frequencyLabel(row.frequency)}</span>,
    },
    {
      key: 'status',
      label: 'Status',
      width: 'minmax(90px, 0.9fr)',
      render: (row) => <StatusBadge value={row.status} />,
    },
    {
      key: 'total',
      label: 'Total',
      width: 'minmax(100px, 1fr)',
      align: 'right',
      render: (row) => formatMoney(row.total, currency),
    },
  ];

  const rowMenu = (row: RecurringInvoice) => (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="ghost" size="sm" className="h-6 w-6 p-0">
          <MoreHorizontal className="h-3.5 w-3.5" />
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end" className="w-48">
        <DropdownMenuItem onSelect={() => onEdit(row.id)}>Edit</DropdownMenuItem>
        <DropdownMenuItem onSelect={() => select(row.id)}>View schedule</DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuItem
          className="text-red-600"
          onSelect={() =>
            setConfirm({
              title: 'Delete this schedule?',
              description:
                'Invoices it has already generated are kept — only the schedule stops. Nothing further will be issued.',
              confirmLabel: 'Delete',
              destructive: true,
              onConfirm: () => {
                remove.mutate(row.id);
                if (filters.selected === row.id) select(null);
              },
            })
          }
        >
          <Trash2 className="mr-2 h-3.5 w-3.5" />
          Delete
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );

  if (error) return <ErrorState error={error} />;

  const toolbar = (
    <>
      <Checkbox
        checked={allChecked}
        onCheckedChange={() => setSelection(allChecked ? new Set() : new Set(rows.map((r) => r.id)))}
      />
      <StatusTabs
        tabs={RECURRING_TABS}
        value={(filters.status as RecurringStatus | null) ?? null}
        onChange={(v) => patch({ status: v })}
      />
      <SearchBox value={filters.search} onChange={(v) => patch({ q: v })} placeholder="Customer…" />
      <div className="ml-auto flex items-center gap-2">
        {filters.isFiltered && (
          <Button variant="ghost" size="sm" className="h-8" onClick={clearFilters}>
            Clear
          </Button>
        )}
        {selection.size > 0 && (
          <Button
            variant="ghost"
            size="sm"
            className="h-8 text-red-600"
            onClick={() =>
              setConfirm({
                title: `Delete ${selection.size} schedules?`,
                description: 'Invoices they have already generated are kept.',
                confirmLabel: 'Delete',
                destructive: true,
                onConfirm: () => {
                  removeMany.mutate([...selection]);
                  setSelection(new Set());
                },
              })
            }
          >
            <Trash2 className="mr-1.5 h-3.5 w-3.5" />
            Delete {selection.size}
          </Button>
        )}
        <Button size="sm" className="h-8" onClick={() => onEdit('new')}>
          <Plus className="mr-1.5 h-3.5 w-3.5" />
          New schedule
        </Button>
      </div>
    </>
  );

  return (
    <>
      <div className="flex h-full min-h-0">
        <div className="min-w-0 flex-1">
          <SectionShell toolbar={toolbar} footer={<Pagination meta={meta} onPage={setPage} />}>
            <SimpleTable
              rows={rows}
              columns={columns}
              rowKey={(r) => r.id}
              selectedKey={filters.selected}
              onRowClick={(r) => select(r.id === filters.selected ? null : r.id)}
              rowMenu={rowMenu}
              empty={
                isLoading ? (
                  <EmptyState icon={Repeat} title="Loading…" />
                ) : (
                  <EmptyState
                    icon={Repeat}
                    title={filters.isFiltered ? 'No schedules match' : 'No recurring invoices'}
                    hint={
                      filters.isFiltered
                        ? 'Try clearing the filters.'
                        : 'A schedule issues the same invoice to a customer on a fixed cadence.'
                    }
                  />
                )
              }
            />
          </SectionShell>
        </div>

        {filters.selected != null && (
          <div className="hidden w-[42%] min-w-[340px] shrink-0 lg:block">
            <RecurringDetail id={filters.selected} onClose={() => select(null)} />
          </div>
        )}
      </div>

      <ConfirmDialog state={confirm} onClose={() => setConfirm(null)} />
    </>
  );
};

/**
 * The schedule pane. Fetched by id rather than taken from the list row because `invoices` is only present on
 * the singular read — the index resource omits the relation.
 */
const RecurringDetail = ({ id, onClose }: { id: number; onClose: () => void }) => {
  const { record, isLoading } = useResourceDetail<RecurringInvoice>('recurring-invoices', id);
  const currency = useCurrency();
  const generated: Invoice[] = record?.invoices ?? [];

  return (
    <div className="flex h-full min-h-0 w-full flex-col border-l border-border bg-background">
      <div className="flex shrink-0 items-start gap-2 border-b border-border px-3 py-2">
        <div className="min-w-0 flex-1">
          <div className="truncate text-xs font-semibold">{record?.customer?.name ?? 'Schedule'}</div>
          <div className="truncate text-[10px] text-muted-foreground">{frequencyLabel(record?.frequency)}</div>
        </div>
        <StatusBadge value={record?.status} />
        <Button variant="ghost" size="sm" className="h-7 px-2" onClick={onClose} title="Close">
          <X className="h-3.5 w-3.5" />
        </Button>
      </div>

      <div className="min-h-0 flex-1 overflow-y-auto p-3">
        {isLoading && <div className="text-xs text-muted-foreground">Loading…</div>}

        {record && (
          <>
            <div className="rounded-lg border border-border px-3 py-1">
              <Field label="Starts at">{formatDate(record.starts_at, record.formatted_starts_at)}</Field>
              <Field label="Next invoice">{formatDate(record.next_invoice_at, record.formatted_next_invoice_at)}</Field>
              <Field label="Frequency">{frequencyLabel(record.frequency)}</Field>
              <Field label="Limit">{limitLabel(record)}</Field>
              <Field label="Sends automatically">{record.send_automatically ? 'Yes' : 'No'}</Field>
              <Field label="Total">{formatMoney(record.total, currency)}</Field>
            </div>

            <div className="mt-3">
              <div className="mb-1.5 text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
                Generated invoices
              </div>
              {generated.length === 0 ? (
                <div className="rounded-lg border border-dashed border-border px-3 py-6 text-center text-xs text-muted-foreground">
                  Nothing issued yet.
                </div>
              ) : (
                <div className="divide-y divide-border/50 rounded-lg border border-border">
                  {generated.map((inv) => (
                    <div key={inv.id} className="flex items-center gap-2 px-3 py-2 text-xs">
                      <span className="font-medium">{inv.invoice_number}</span>
                      <StatusBadge value={inv.status} />
                      <span className="ml-auto tabular-nums">{formatMoney(inv.total, currency)}</span>
                    </div>
                  ))}
                </div>
              )}
            </div>

            {record.notes && (
              <div className="mt-3 rounded-lg border border-border p-3 text-xs text-muted-foreground">
                {record.notes}
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
};

const limitLabel = (row: RecurringInvoice): string => {
  if (row.limit_by === 'COUNT') return `${row.limit_count ?? 0} invoices`;
  if (row.limit_by === 'DATE') return formatDate(row.limit_date, row.formatted_limit_date);
  return 'None';
};
