import type { Column } from './components';
import type { ConfirmState } from './ConfirmDialog';
import type { Expense } from './shared';
import { useState } from 'react';
import { Copy, Filter, MoreHorizontal, Paperclip, Plus, Receipt, Trash2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { EmptyState, ErrorState, Pagination, SearchBox, SectionShell, SimpleTable } from './components';
import { ConfirmDialog } from './ConfirmDialog';
import { formatDate, formatMoney } from './format';
import { PAGE_SIZE } from './shared';
import { useListFilters } from './useInvoicesSection';
import {
  useCurrency,
  useDocumentAction,
  useLookups,
  useResourceList,
  useResourceMutations,
} from './useInvoiceShelfData';

// Expenses — money going the other way, and the only list with a file attached to its rows.
//
// The receipt link opens `attachment_receipt_url` directly. That URL is InvoiceShelf's own, rendered from the
// instance's APP_URL, so it is a browser-resolvable link rather than something proxied through the sidecar —
// which means it only works from a machine that can reach the InvoiceShelf host. Left as-is deliberately:
// proxying arbitrary uploaded files is a wider surface than this screen needs.

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

export const ExpensesListView = ({ onEdit }: Props) => {
  const { filters, patch, setPage, clearFilters } = useListFilters();
  const currency = useCurrency();
  const { customers, categories } = useLookups();
  const [showFilters, setShowFilters] = useState(false);
  const [selection, setSelection] = useState<Set<number>>(new Set());
  const [confirm, setConfirm] = useState<ConfirmState>(null);

  const { rows, meta, isLoading, error } = useResourceList<Expense>('expenses', {
    page: filters.page,
    limit: PAGE_SIZE,
    search: filters.search || undefined,
    customer_id: filters.customerId || undefined,
    expense_category_id: filters.status || undefined,
    from_date: filters.fromDate || undefined,
    to_date: filters.toDate || undefined,
    orderByField: 'expense_date',
    orderBy: 'desc',
  });

  const { remove, removeMany } = useResourceMutations('expenses');
  const action = useDocumentAction('expenses');

  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<Expense>[] = [
    {
      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: 'expense_date',
      label: 'Date',
      width: 'minmax(90px, 0.8fr)',
      render: (row) => formatDate(row.expense_date, row.formatted_expense_date),
    },
    {
      key: 'expense_number',
      label: 'Number',
      width: 'minmax(90px, 0.8fr)',
      render: (row) => <span className="font-medium">{row.expense_number ?? '—'}</span>,
    },
    {
      key: 'category',
      label: 'Category',
      width: 'minmax(100px, 1fr)',
      render: (row) => <span className="truncate">{row.expense_category?.name ?? '—'}</span>,
    },
    {
      key: 'customer',
      label: 'Customer',
      width: 'minmax(100px, 1fr)',
      render: (row) => <span className="truncate text-muted-foreground">{row.customer?.name ?? '—'}</span>,
    },
    {
      key: 'notes',
      label: 'Notes',
      width: 'minmax(120px, 1.4fr)',
      render: (row) => (
        <span className="flex min-w-0 items-center gap-1.5">
          {row.attachment_receipt_url && (
            <a
              href={row.attachment_receipt_url}
              target="_blank"
              rel="noopener noreferrer"
              onClick={(e) => e.stopPropagation()}
              title="Open receipt"
              className="shrink-0 text-muted-foreground hover:text-foreground"
            >
              <Paperclip className="h-3 w-3" />
            </a>
          )}
          <span className="truncate text-muted-foreground">{row.notes ?? '—'}</span>
        </span>
      ),
    },
    {
      key: 'amount',
      label: 'Amount',
      width: 'minmax(100px, 1fr)',
      align: 'right',
      render: (row) => formatMoney(row.amount, currency),
    },
  ];

  const rowMenu = (row: Expense) => (
    <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={() => action.mutate({ id: row.id, action: 'duplicate' })}>
          <Copy className="mr-2 h-3.5 w-3.5" />
          Duplicate
        </DropdownMenuItem>
        {row.attachment_receipt_url && (
          <DropdownMenuItem onSelect={() => window.open(row.attachment_receipt_url ?? '', '_blank', 'noopener')}>
            <Paperclip className="mr-2 h-3.5 w-3.5" />
            Open receipt
          </DropdownMenuItem>
        )}
        <DropdownMenuSeparator />
        <DropdownMenuItem
          className="text-red-600"
          onSelect={() =>
            setConfirm({
              title: 'Delete this expense?',
              description: 'It disappears from the profit & loss and expense reports.',
              confirmLabel: 'Delete',
              destructive: true,
              onConfirm: () => remove.mutate(row.id),
            })
          }
        >
          <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)))}
      />
      <SearchBox value={filters.search} onChange={(v) => patch({ q: v })} placeholder="Notes…" />
      <Button
        variant={showFilters || filters.isFiltered ? 'secondary' : 'ghost'}
        size="sm"
        className="h-8"
        onClick={() => setShowFilters((v) => !v)}
      >
        <Filter className="mr-1.5 h-3.5 w-3.5" />
        Filter
      </Button>
      <div className="ml-auto flex items-center gap-2">
        {selection.size > 0 && (
          <Button
            variant="ghost"
            size="sm"
            className="h-8 text-red-600"
            onClick={() =>
              setConfirm({
                title: `Delete ${selection.size} expenses?`,
                description: 'They disappear from the profit & loss and expense reports.',
                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 expense
        </Button>
      </div>
    </>
  );

  return (
    <>
      <SectionShell toolbar={toolbar} footer={<Pagination meta={meta} onPage={setPage} />}>
        {showFilters && (
          <div className="flex flex-wrap items-end gap-3 border-b border-border bg-muted/20 px-3 py-2">
            <label className="flex flex-col gap-1 text-[10px] text-muted-foreground">
              Category
              <select
                value={filters.status ?? ''}
                onChange={(e) => patch({ status: e.target.value || null })}
                className="h-8 rounded-md border border-input bg-background px-2 text-xs"
              >
                <option value="">All</option>
                {categories.map((c) => (
                  <option key={c.id} value={c.id}>
                    {c.name}
                  </option>
                ))}
              </select>
            </label>
            <label className="flex flex-col gap-1 text-[10px] text-muted-foreground">
              Customer
              <select
                value={filters.customerId ?? ''}
                onChange={(e) => patch({ customer: e.target.value || null })}
                className="h-8 rounded-md border border-input bg-background px-2 text-xs"
              >
                <option value="">All</option>
                {customers.map((c) => (
                  <option key={c.id} value={c.id}>
                    {c.name}
                  </option>
                ))}
              </select>
            </label>
            <label className="flex flex-col gap-1 text-[10px] text-muted-foreground">
              From
              <Input
                type="date"
                value={filters.fromDate ?? ''}
                onChange={(e) => patch({ from: e.target.value || null })}
                className="h-8 w-36 text-xs"
              />
            </label>
            <label className="flex flex-col gap-1 text-[10px] text-muted-foreground">
              To
              <Input
                type="date"
                value={filters.toDate ?? ''}
                onChange={(e) => patch({ to: e.target.value || null })}
                className="h-8 w-36 text-xs"
              />
            </label>
            {filters.isFiltered && (
              <Button variant="ghost" size="sm" className="h-8" onClick={clearFilters}>
                Clear
              </Button>
            )}
          </div>
        )}

        <SimpleTable
          rows={rows}
          columns={columns}
          rowKey={(r) => r.id}
          onRowClick={(r) => onEdit(r.id)}
          rowMenu={rowMenu}
          empty={
            isLoading ? (
              <EmptyState icon={Receipt} title="Loading…" />
            ) : (
              <EmptyState
                icon={Receipt}
                title={filters.isFiltered ? 'No expenses match' : 'No expenses yet'}
                hint={
                  filters.isFiltered
                    ? 'Try clearing the filters.'
                    : 'Recording expenses is what makes the net income figure mean anything.'
                }
              />
            )
          }
        />
      </SectionShell>

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