'use client';

import { useMemo, useState } from 'react';
import { useParams } from 'next/navigation';
import { Plus, Download, FileText, FileSpreadsheet } from 'lucide-react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';

import { Button } from '@/components/ui/button';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { DataTable } from '@/components/shared/data-table';
import { FilterBar } from '@/components/shared/filter-bar';
import { PageHeader } from '@/components/shared/page-header';
import { EmptyState } from '@/components/shared/empty-state';
import { TableSkeleton } from '@/components/shared/loading-skeleton';
import { ArchiveConfirmDialog } from '@/components/shared/archive-confirm-dialog';
import { PermissionGate } from '@/components/shared/permission-gate';
import { ExpenseFormDialog } from '@/components/expenses/expense-form-dialog';
import { ExpenseCard } from '@/components/expenses/expense-card';
import { buildExpenseFilterDefinitions } from '@/components/expenses/expense-filters';
import { getExpenseColumns, type ExpenseRow } from '@/components/expenses/expense-columns';
import { useCreateFromUrl } from '@/hooks/use-create-from-url';
import { usePaginatedQuery } from '@/hooks/use-paginated-query';
import { useRealtimeInvalidation } from '@/hooks/use-realtime-invalidation';
import { apiFetch } from '@/lib/api/client';
import { triggerBlobDownload } from '@/lib/utils/download';

export default function ExpensesPage() {
  const params = useParams<{ portSlug: string }>();
  const portSlug = params?.portSlug ?? '';
  const queryClient = useQueryClient();

  // Per-port category override. Falls back to shipped defaults until the
  // vocab call resolves, so the filter bar always renders something.
  const { data: vocab } = useQuery<{ data: Record<string, readonly string[]> }>({
    queryKey: ['vocabularies'],
    queryFn: () => apiFetch('/api/v1/vocabularies'),
    staleTime: 5 * 60_000,
  });
  const filterDefs = useMemo(
    () => buildExpenseFilterDefinitions(vocab?.data?.expense_categories),
    [vocab],
  );

  const [createOpen, setCreateOpen] = useState(false);
  useCreateFromUrl(() => setCreateOpen(true));
  const [editExpense, setEditExpense] = useState<ExpenseRow | null>(null);
  const [archiveExpense, setArchiveExpense] = useState<ExpenseRow | null>(null);

  const {
    data,
    pagination,
    isLoading,
    isFetching,
    sort,
    setSort,
    setPage,
    setPageSize,
    filters,
    setFilter,
    clearFilters,
  } = usePaginatedQuery<ExpenseRow>({
    queryKey: ['expenses'],
    endpoint: '/api/v1/expenses',
    filterDefinitions: filterDefs,
  });

  useRealtimeInvalidation({
    'expense:created': [['expenses']],
    'expense:updated': [['expenses']],
    'expense:archived': [['expenses']],
  });

  const archiveMutation = useMutation({
    mutationFn: (id: string) => apiFetch(`/api/v1/expenses/${id}`, { method: 'DELETE' }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['expenses'] });
      setArchiveExpense(null);
    },
  });

  async function handleExport(type: 'csv' | 'pdf') {
    const res = await fetch(`/api/v1/expenses/export/${type}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(filters),
      credentials: 'include',
    });
    if (!res.ok) return;
    const blob = await res.blob();
    triggerBlobDownload(blob, `expenses.${type}`);
  }

  const columns = getExpenseColumns({
    portSlug,
    onEdit: (expense) => setEditExpense(expense),
    onArchive: (expense) => setArchiveExpense(expense),
  });

  return (
    <div className="space-y-4">
      <PageHeader
        title="Expenses"
        description="Track and manage business expenses"
        actions={
          <div className="flex items-center gap-2">
            <PermissionGate resource="expenses" action="view">
              <DropdownMenu>
                <DropdownMenuTrigger asChild>
                  <Button variant="outline" size="sm">
                    <Download className="mr-1.5 h-4 w-4" />
                    Export
                  </Button>
                </DropdownMenuTrigger>
                <DropdownMenuContent align="end">
                  <DropdownMenuItem onClick={() => handleExport('csv')}>
                    <FileSpreadsheet className="mr-2 h-4 w-4" />
                    Export CSV
                  </DropdownMenuItem>
                  <DropdownMenuItem onClick={() => handleExport('pdf')}>
                    <FileText className="mr-2 h-4 w-4" />
                    Export PDF
                  </DropdownMenuItem>
                </DropdownMenuContent>
              </DropdownMenu>
            </PermissionGate>

            <PermissionGate resource="expenses" action="create">
              <Button size="sm" onClick={() => setCreateOpen(true)}>
                <Plus className="mr-1.5 h-4 w-4" />
                New Expense
              </Button>
            </PermissionGate>
          </div>
        }
      />

      <FilterBar
        filters={filterDefs}
        values={filters}
        onChange={setFilter}
        onClear={clearFilters}
      />

      {isLoading ? (
        <TableSkeleton />
      ) : (
        <DataTable
          columns={columns}
          data={data}
          pagination={pagination}
          onPaginationChange={(p, ps) => {
            setPage(p);
            setPageSize(ps);
          }}
          sort={sort}
          onSortChange={setSort}
          isLoading={isFetching && !isLoading}
          getRowId={(row) => row.id}
          cardRender={(row) => (
            <ExpenseCard
              expense={row.original}
              portSlug={portSlug}
              onEdit={setEditExpense}
              onArchive={setArchiveExpense}
            />
          )}
          emptyState={
            <EmptyState
              title="No expenses found"
              description="Get started by adding your first expense."
              action={{ label: 'New Expense', onClick: () => setCreateOpen(true) }}
            />
          }
        />
      )}

      <ExpenseFormDialog open={createOpen} onOpenChange={setCreateOpen} />

      {editExpense && (
        <ExpenseFormDialog
          open={!!editExpense}
          onOpenChange={(open) => !open && setEditExpense(null)}
          expense={editExpense}
        />
      )}

      <ArchiveConfirmDialog
        open={!!archiveExpense}
        onOpenChange={(open) => !open && setArchiveExpense(null)}
        entityName={archiveExpense?.establishmentName ?? 'this expense'}
        entityType="Expense"
        isArchived={false}
        onConfirm={() => archiveExpense && archiveMutation.mutate(archiveExpense.id)}
        isLoading={archiveMutation.isPending}
      />
    </div>
  );
}
