'use client'

import React, { useEffect, useState, useCallback, useRef } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { PanelGroup, Panel, PanelResizeHandle } from 'react-resizable-panels';
import { Card } from '@alga-psa/ui/components/Card';
import { Button } from '@alga-psa/ui/components/Button';
import { Input } from '@alga-psa/ui/components/Input';
import { Checkbox } from '@alga-psa/ui/components/Checkbox';
import { DataTable } from '@alga-psa/ui/components/DataTable';
import { Badge } from '@alga-psa/ui/components/Badge';
import { Alert, AlertDescription } from '@alga-psa/ui/components/Alert';
import { FileText, MoreVertical, GripVertical, Search, CheckCircle, Download, ArrowRight, RotateCcw } from 'lucide-react';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@alga-psa/ui/components/DropdownMenu';
import type { ColumnDefinition, InvoiceViewModel as DbInvoiceViewModel, IInvoiceTemplate } from '@alga-psa/types';
import { fetchInvoicesPaginated } from '@alga-psa/billing/actions/invoiceQueries';
import { getInvoiceTemplates } from '@alga-psa/billing/actions/invoiceTemplates';
import { finalizeInvoice, hardDeleteInvoice } from '@alga-psa/billing/actions/invoiceModification';
import { validateInvoiceFinalization, updateInvoiceTaxSource } from '@alga-psa/billing/actions/taxSourceActions';
import { downloadInvoicePDF } from '@alga-psa/billing/actions/invoiceGeneration';
import { toPlainDate } from '@alga-psa/core';
import InvoicePreviewPanel from './InvoicePreviewPanel';
import LoadingIndicator from '@alga-psa/ui/components/LoadingIndicator';
import { ConfirmationDialog } from '@alga-psa/ui/components/ConfirmationDialog';
import { useFormatters, useTranslation } from '@alga-psa/ui/lib/i18n/client';
import { useRangeSelection } from '@alga-psa/ui/hooks';
import { InvoiceSyncBadge } from '../../invoices/InvoiceSyncBadge';
import { useInvoiceSyncStatuses } from '../../invoices/useInvoiceSyncStatuses';

interface DraftsTabProps {
  onRefreshNeeded: () => void;
  refreshTrigger: number;
}

const DraftsTab: React.FC<DraftsTabProps> = ({
  onRefreshNeeded,
  refreshTrigger
}) => {
  const { t } = useTranslation('msp/invoicing');
  const { formatCurrency, formatDate } = useFormatters();
  const router = useRouter();
  const searchParams = useSearchParams();

  const [invoices, setInvoices] = useState<DbInvoiceViewModel[]>([]);
  const [templates, setTemplates] = useState<IInvoiceTemplate[]>([]);
  const [selectedInvoices, setSelectedInvoices] = useState<Set<string>>(new Set());
  const [searchTerm, setSearchTerm] = useState('');
  const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [tableKey, setTableKey] = useState(0);
  const [reverseDialogState, setReverseDialogState] = useState<{ isOpen: boolean; invoiceIds: string[] }>({ isOpen: false, invoiceIds: [] });
  const [isReverseConfirming, setIsReverseConfirming] = useState(false);
  // Escape hatch for invoices blocked from finalizing because they await external tax import.
  const [taxSourceFixState, setTaxSourceFixState] = useState<{ isOpen: boolean; invoiceId: string | null; invoiceNumber: string | null }>({ isOpen: false, invoiceId: null, invoiceNumber: null });
  const [isFixingTaxSource, setIsFixingTaxSource] = useState(false);
  // Sticky notice for bulk-finalize results (e.g. invoices skipped). Kept separate from
  // `error` because loadData() resets `error`, and the post-finalize refresh would
  // otherwise wipe this message before the user can read it.
  const [finalizeNotice, setFinalizeNotice] = useState<string | null>(null);

  // Pagination state - server-side
  const [currentPage, setCurrentPage] = useState(1);
  const [pageSize, setPageSize] = useState(10);
  const [totalInvoices, setTotalInvoices] = useState(0);

  // Ref to track if initial load has happened
  const initialLoadDone = useRef(false);

  const selectedInvoiceId = searchParams?.get('invoiceId') ?? null;
  const selectedTemplateId = searchParams?.get('templateId') ?? null;

  // Debounce search term
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedSearchTerm(searchTerm);
      // Reset to page 1 and clear selection when search changes
      if (initialLoadDone.current) {
        setCurrentPage(1);
        setSelectedInvoices(new Set());
        setFinalizeNotice(null);
      }
    }, 300);

    return () => clearTimeout(timer);
  }, [searchTerm]);

  // Handle page size change - reset to page 1 and clear selection
  const handlePageSizeChange = (newPageSize: number) => {
    setPageSize(newPageSize);
    setCurrentPage(1);
    setSelectedInvoices(new Set());
    setFinalizeNotice(null);
  };

  // Handle page change - clear selection (server-side pagination means selected items may not be visible)
  const handlePageChange = (newPage: number) => {
    setCurrentPage(newPage);
    setSelectedInvoices(new Set());
    setFinalizeNotice(null);
  };

  // Load data when pagination, search, or refresh changes
  useEffect(() => {
    loadData();
  }, [currentPage, pageSize, debouncedSearchTerm, refreshTrigger]);

  const loadData = async (options: { silent?: boolean } = {}) => {
    if (!options.silent) {
      setIsLoading(true);
    }
    setError(null);
    try {
      const [paginatedResult, fetchedTemplates] = await Promise.all([
        fetchInvoicesPaginated({
          page: currentPage,
          pageSize: pageSize,
          searchTerm: debouncedSearchTerm,
          status: 'draft',
          sortBy: 'invoice_date',
          sortOrder: 'desc'
        }),
        getInvoiceTemplates()
      ]);

      setInvoices(paginatedResult.invoices);
      setTotalInvoices(paginatedResult.total);
      setTemplates(fetchedTemplates);
      initialLoadDone.current = true;

      // Clamp page if current page is beyond available pages (e.g., after delete/filter)
      const maxPage = Math.max(1, Math.ceil(paginatedResult.total / pageSize));
      if (currentPage > maxPage) {
        setCurrentPage(maxPage);
        setSelectedInvoices(new Set()); // Clear selection since visible rows changed
      }
    } catch (err) {
      console.error('Error fetching draft invoices data:', err);
      setError(t('draftsTab.errors.loadFailed', {
        defaultValue: 'Failed to load draft invoices. Please try again.',
      }));
    } finally {
      if (!options.silent) {
        setIsLoading(false);
      }
    }
  };

  // For server-side pagination, filteredInvoices is just invoices (already filtered server-side)
  const filteredInvoices = invoices;

  const invoiceIds = filteredInvoices.map((inv) => inv.invoice_id);
  const { statuses: syncStatuses, hidden: syncHidden } = useInvoiceSyncStatuses(invoiceIds);

  const selectedInvoice = selectedInvoiceId ? invoices.find(inv => inv.invoice_id === selectedInvoiceId) || null : null;

  const updateUrlParams = (params: { [key: string]: string | null }) => {
    const newParams = new URLSearchParams(window.location.search);

    if (!newParams.has('tab')) newParams.set('tab', 'invoicing');
    newParams.set('subtab', 'drafts');

    Object.entries(params).forEach(([key, value]) => {
      if (value === null) {
        newParams.delete(key);
      } else {
        newParams.set(key, value);
      }
    });

    const newUrl = `${window.location.pathname}?${newParams.toString()}`;
    window.history.pushState(null, '', newUrl);
  };

  const handleSelectAll = (checked: boolean) => {
    if (checked) {
      setSelectedInvoices(new Set(filteredInvoices.map(inv => inv.invoice_id)));
    } else {
      setSelectedInvoices(new Set());
    }
  };

  const rangeSelect = useRangeSelection<DbInvoiceViewModel>({
    items: filteredInvoices,
    getId: (invoice) => invoice.invoice_id,
    selectedIds: selectedInvoices,
    onSelectedIdsChange: setSelectedInvoices,
  });

  const handleInvoiceSelect = (invoice: DbInvoiceViewModel) => {
    if (selectedInvoiceId === invoice.invoice_id) {
      updateUrlParams({ invoiceId: null, templateId: null });
    } else {
      updateUrlParams({
        invoiceId: invoice.invoice_id,
        templateId: selectedTemplateId
      });
    }
  };

  const handleFinalizeSingle = async (invoiceId: string) => {
    setError(null);
    setFinalizeNotice(null);
    try {
      // Pre-validate so we can surface the actual blocking reason. Thrown server-action
      // errors are masked in production, so we rely on this returned shape instead of the
      // exception text below.
      const validation = await validateInvoiceFinalization(invoiceId);
      if (!validation.canFinalize) {
        if (validation.code === 'pending_external_tax') {
          // Offer the escape hatch (switch to internal tax) rather than a dead-end message.
          const invoice = invoices.find(inv => inv.invoice_id === invoiceId);
          setTaxSourceFixState({ isOpen: true, invoiceId, invoiceNumber: invoice?.invoice_number ?? null });
          return;
        }
        setError(validation.error ?? t('draftsTab.errors.finalizeFailed', {
          defaultValue: 'Failed to finalize invoice. Please try again.',
        }));
        return;
      }

      await finalizeInvoice(invoiceId);
      await loadData();
      onRefreshNeeded();
      setSelectedInvoices(prev => {
        const next = new Set(prev);
        next.delete(invoiceId);
        return next;
      });
      if (selectedInvoiceId === invoiceId) {
        updateUrlParams({ invoiceId: null, templateId: null });
      }
    } catch (err) {
      console.error('Failed to finalize invoice:', err);
      setError(t('draftsTab.errors.finalizeFailed', {
        defaultValue: 'Failed to finalize invoice. Please try again.',
      }));
    }
  };

  // Escape hatch: switch a draft from external tax delegation back to internal tax
  // calculation, then finalize it. Used when an invoice is stuck in `pending_external`
  // and the tenant is not actually completing the export/import accounting cycle.
  const handleSwitchToInternalAndFinalize = async () => {
    const invoiceId = taxSourceFixState.invoiceId;
    if (!invoiceId) return;
    setIsFixingTaxSource(true);
    setError(null);
    setFinalizeNotice(null);
    try {
      const result = await updateInvoiceTaxSource(invoiceId, 'internal');
      if (!result.success) {
        setError(result.error ?? t('draftsTab.errors.finalizeFailed', {
          defaultValue: 'Failed to finalize invoice. Please try again.',
        }));
        return;
      }
      await finalizeInvoice(invoiceId);
      await loadData();
      onRefreshNeeded();
      setSelectedInvoices(prev => {
        const next = new Set(prev);
        next.delete(invoiceId);
        return next;
      });
      if (selectedInvoiceId === invoiceId) {
        updateUrlParams({ invoiceId: null, templateId: null });
      }
      setTaxSourceFixState({ isOpen: false, invoiceId: null, invoiceNumber: null });
    } catch (err) {
      console.error('Failed to switch tax source and finalize invoice:', err);
      setError(t('draftsTab.errors.finalizeFailed', {
        defaultValue: 'Failed to finalize invoice. Please try again.',
      }));
    } finally {
      setIsFixingTaxSource(false);
    }
  };

  const openReverseDialog = (invoiceIds: string[]) => {
    setReverseDialogState({ isOpen: true, invoiceIds });
  };

  const handleFinalizeFromPreview = async () => {
    if (!selectedInvoice) return;
    await handleFinalizeSingle(selectedInvoice.invoice_id);
  };

  const handleReverseFromPreview = async () => {
    if (!selectedInvoice) return;
    openReverseDialog([selectedInvoice.invoice_id]);
  };

  const handleBulkFinalize = async () => {
    setError(null);
    setFinalizeNotice(null);
    try {
      // Pre-validate each invoice so blocked ones (e.g. awaiting external tax import) are
      // skipped with an accurate explanation rather than aborting the whole batch.
      let blockedByPendingTax = 0;
      let otherBlocked = 0;
      for (const invoiceId of selectedInvoices) {
        const validation = await validateInvoiceFinalization(invoiceId);
        if (!validation.canFinalize) {
          if (validation.code === 'pending_external_tax') {
            blockedByPendingTax += 1;
          } else {
            otherBlocked += 1;
          }
          continue;
        }
        await finalizeInvoice(invoiceId);
      }
      setSelectedInvoices(new Set());
      await loadData();
      onRefreshNeeded();
      updateUrlParams({ invoiceId: null, templateId: null });

      if (blockedByPendingTax > 0) {
        setFinalizeNotice(t('draftsTab.errors.bulkFinalizePendingTax', {
          count: blockedByPendingTax,
          defaultValue: `${blockedByPendingTax} invoice(s) were skipped because they are awaiting external tax import. Import the tax from your accounting system, or switch them to internal tax, then finalize them individually.`,
        }));
      } else if (otherBlocked > 0) {
        setFinalizeNotice(t('draftsTab.errors.bulkFinalizeSkipped', {
          count: otherBlocked,
          defaultValue: `${otherBlocked} invoice(s) could not be finalized and were skipped.`,
        }));
      }
    } catch (err) {
      console.error('Failed to finalize selected invoices:', err);
      setError(t('draftsTab.errors.bulkFinalizeFailed', {
        defaultValue: 'Failed to finalize selected invoices. Please try again.',
      }));
    }
  };

  const handleBulkReverse = async () => {
    if (selectedInvoices.size === 0) return;
    openReverseDialog(Array.from(selectedInvoices));
  };

  const handleDownload = async () => {
    if (!selectedInvoice) return;
    setError(null);
    try {
      const { pdfData, invoiceNumber } = await downloadInvoicePDF(selectedInvoice.invoice_id, selectedTemplateId);

      const blob = new Blob([new Uint8Array(pdfData)], { type: 'application/pdf' });
      const blobUrl = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = blobUrl;
      link.setAttribute('download', `${invoiceNumber}.pdf`);
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(blobUrl);
    } catch (err) {
      console.error('Failed to generate PDF:', err);
      setError(t('draftsTab.errors.pdfFailed', {
        defaultValue: 'Failed to generate PDF. Please try again.',
      }));
    }
  };

  const columns: ColumnDefinition<DbInvoiceViewModel>[] = [
    {
      title: (
        <div className="flex items-center">
          <Checkbox
            id="select-all-drafts"
            checked={selectedInvoices.size > 0 && selectedInvoices.size === filteredInvoices.length}
            onChange={(e) => handleSelectAll((e.target as HTMLInputElement).checked)}
          />
        </div>
      ),
      dataIndex: 'invoice_id',
      width: '50px',
      render: (_, record) => (
        <div className="flex items-center" onClick={(e) => e.stopPropagation()}>
          <Checkbox
            id={`draft-${record.invoice_id}`}
            checked={rangeSelect.isSelected(record.invoice_id)}
            onClick={(event: React.MouseEvent<HTMLInputElement>) => {
              event.stopPropagation();
              const isChecked = rangeSelect.isSelected(record.invoice_id);
              rangeSelect.handleSelect(record.invoice_id, {
                shiftKey: event.shiftKey,
                selected: !isChecked,
                preventDefault: () => event.preventDefault(),
              });
              event.preventDefault();
            }}
            onChange={() => { /* controlled via onClick for shift-range support */ }}
          />
        </div>
      ),
    },
    {
      title: t('draftsTab.columns.invoiceNumber', { defaultValue: 'Invoice Number' }),
      dataIndex: 'invoice_number',
    },
    {
      title: t('draftsTab.columns.client', { defaultValue: 'Client' }),
      dataIndex: ['client', 'name'],
    },
    {
      title: t('draftsTab.columns.amount', { defaultValue: 'Amount' }),
      dataIndex: 'total_amount',
      render: (value, record) => formatCurrency(Number(value) / 100, record.currencyCode || 'USD', {
        minimumFractionDigits: 2,
      }),
    },
    {
      title: t('draftsTab.columns.invoiceDate', { defaultValue: 'Invoice Date' }),
      dataIndex: 'invoice_date',
      render: (value) => formatDate(toPlainDate(value).toString()),
    },
    {
      title: t('draftsTab.columns.dueDate', { defaultValue: 'Due Date' }),
      dataIndex: 'due_date',
      render: (value) => value ? formatDate(toPlainDate(value).toString()) : '',
    },
    {
      title: t('draftsTab.columns.status', { defaultValue: 'Status' }),
      dataIndex: 'status',
      render: () => (
        <Badge variant="warning">
          {t('draftsTab.status.draft', { defaultValue: 'Draft' })}
        </Badge>
      ),
    },
    ...(syncHidden ? [] : [{
      title: t('draftsTab.columns.quickbooks', { defaultValue: 'QuickBooks' }),
      dataIndex: 'invoice_id' as const,
      render: (_: unknown, record: DbInvoiceViewModel) => {
        const syncStatus = syncStatuses[record.invoice_id];
        if (!syncStatus) return null;
        return <InvoiceSyncBadge status={syncStatus} environment={syncStatus.environment} />;
      },
    }]),
    {
      title: t('draftsTab.columns.actions', { defaultValue: 'Actions' }),
      dataIndex: 'invoice_id',
      width: '5%',
      render: (_, record) => (
        <div onClick={(e) => e.stopPropagation()}>
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button
                id={`draft-row-actions-${record.invoice_id}`}
                variant="ghost"
                className="h-8 w-8 p-0"
                aria-label={t('common.actions.openMenu', { defaultValue: 'Open menu' })}
              >
                <MoreVertical className="h-4 w-4" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              <DropdownMenuItem
                onClick={async () => await handleFinalizeSingle(record.invoice_id)}
                className="flex items-center gap-2"
                id={`finalize-draft-${record.invoice_id}-menu-item`}
              >
                <CheckCircle className="h-4 w-4" />
                {t('draftsTab.actions.finalize', { defaultValue: 'Finalize' })}
              </DropdownMenuItem>
              <DropdownMenuItem
                onClick={async () => {
                  try {
                    const { pdfData, invoiceNumber } = await downloadInvoicePDF(record.invoice_id);
                    const blob = new Blob([new Uint8Array(pdfData)], { type: 'application/pdf' });
                    const blobUrl = window.URL.createObjectURL(blob);
                    const link = document.createElement('a');
                    link.href = blobUrl;
                    link.setAttribute('download', `${invoiceNumber}.pdf`);
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                    window.URL.revokeObjectURL(blobUrl);
                  } catch (err) {
                    console.error('Failed to generate PDF:', err);
                    setError(t('draftsTab.errors.pdfFailed', {
                      defaultValue: 'Failed to generate PDF. Please try again.',
                    }));
                  }
                }}
                className="flex items-center gap-2"
                id={`download-draft-${record.invoice_id}-menu-item`}
              >
                <Download className="h-4 w-4" />
                {t('draftsTab.actions.downloadPdf', { defaultValue: 'Download PDF' })}
              </DropdownMenuItem>
              <DropdownMenuItem
                onClick={() => openReverseDialog([record.invoice_id])}
                className="flex items-center gap-2 text-red-600 focus:text-red-600"
                id={`reverse-draft-${record.invoice_id}-menu-item`}
              >
                <RotateCcw className="h-4 w-4" />
                {t('draftsTab.actions.reverseDraft', { defaultValue: 'Reverse Draft' })}
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      ),
    },
  ];

  return (
    <div className="space-y-4">
      <div className="flex justify-between items-center">
        <div className="flex items-center gap-4 flex-1 max-w-md">
          <div className="relative flex-1">
            <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" aria-hidden="true" />
            <Input
              type="text"
              placeholder={t('draftsTab.searchPlaceholder', { defaultValue: 'Search invoices...' })}
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="pl-10"
              aria-label={t('draftsTab.searchPlaceholder', { defaultValue: 'Search invoices...' })}
            />
          </div>
        </div>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              id="drafts-bulk-actions-trigger"
              variant="outline"
              disabled={selectedInvoices.size === 0}
              className="flex items-center gap-2"
            >
              {t('draftsTab.bulkActions', {
                count: selectedInvoices.size,
                defaultValue: `Actions (${selectedInvoices.size})`,
              })}
              <MoreVertical className="w-4 h-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            <DropdownMenuItem onClick={handleBulkFinalize} className="flex items-center gap-2" id="finalize-selected-drafts-menu-item">
              <CheckCircle className="h-4 w-4" />
              {t('draftsTab.actions.finalizeSelected', { defaultValue: 'Finalize Selected' })}
            </DropdownMenuItem>
            <DropdownMenuItem onClick={handleBulkReverse} className="flex items-center gap-2 text-red-600 focus:text-red-600" id="reverse-selected-drafts-menu-item">
              <RotateCcw className="h-4 w-4" />
              {t('draftsTab.actions.reverseSelected', { defaultValue: 'Reverse Selected' })}
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </div>

      {error && (
        <Alert variant="destructive" className="mb-4">
          <AlertDescription>{error}</AlertDescription>
        </Alert>
      )}

      {finalizeNotice && (
        <Alert variant="warning" className="mb-4">
          <AlertDescription>{finalizeNotice}</AlertDescription>
        </Alert>
      )}

      {isLoading ? (
        <Card>
          <div className="p-12 flex items-center justify-center">
            <LoadingIndicator
              text={t('draftsTab.loading', { defaultValue: 'Loading draft invoices...' })}
              spinnerProps={{ size: 'md' }}
              layout="stacked"
              textClassName="text-muted-foreground"
            />
          </div>
        </Card>
      ) : filteredInvoices.length === 0 ? (
        <Card>
          <div className="p-12 text-center">
            <FileText className="h-12 w-12 mx-auto mb-4 text-muted-foreground" />
            <h3 className="text-lg font-semibold text-[rgb(var(--color-text-900))] mb-2">
              {t('draftsTab.empty.title', { defaultValue: 'No Draft Invoices' })}
            </h3>
            <p className="text-muted-foreground mb-4">
              {t('draftsTab.empty.description', {
                defaultValue: 'Draft invoices will appear here once you create invoices that have not been finalized.',
              })}
            </p>
            <Button
              id="drafts-view-generate"
              onClick={() => router.push('/msp/billing?tab=invoicing&subtab=generate')}
              className="flex items-center gap-2"
            >
              {t('draftsTab.actions.generateInvoices', { defaultValue: 'Generate Invoices' })}
              <ArrowRight className="h-4 w-4" />
            </Button>
          </div>
        </Card>
      ) : (
        <PanelGroup direction="horizontal" className="min-h-[600px]">
          <Panel defaultSize={60} minSize={30} onResize={() => setTableKey(prev => prev + 1)}>
            <div className="pr-2">
              <DataTable
                id="invoice-drafts-table"
                key={`${tableKey}-${currentPage}-${pageSize}`}
                data={filteredInvoices}
                columns={columns}
                pagination={true}
                currentPage={currentPage}
                onPageChange={handlePageChange}
                pageSize={pageSize}
                onItemsPerPageChange={handlePageSizeChange}
                totalItems={totalInvoices}
                onRowClick={handleInvoiceSelect}
                rowClassName={(record) =>
                  selectedInvoiceId === record.invoice_id ? 'bg-table-selected' : ''
                }
              />
            </div>
          </Panel>

          <PanelResizeHandle className="w-2 hover:bg-[rgb(var(--color-primary-50))] transition-colors relative flex items-center justify-center group">
            <div className="absolute inset-y-0 w-1 bg-[rgb(var(--color-border-200))] group-hover:bg-[rgb(var(--color-primary-400))] transition-colors"></div>
            <GripVertical className="h-4 w-4 text-[rgb(var(--color-text-400))] group-hover:text-[rgb(var(--color-primary-600))] relative z-10" />
          </PanelResizeHandle>

          <Panel defaultSize={40} minSize={30}>
            <div className="pl-2">
              <InvoicePreviewPanel
                key={`draft-${selectedInvoiceId}`}
                invoiceId={selectedInvoiceId}
                templates={templates}
                selectedTemplateId={selectedTemplateId}
                onTemplateChange={(templateId) => updateUrlParams({ templateId })}
                onFinalize={handleFinalizeFromPreview}
                onReverse={handleReverseFromPreview}
                onDownload={handleDownload}
                onDraftInvoiceUpdated={async () => {
                  await loadData({ silent: true });
                }}
                isFinalized={false}
                creditApplied={selectedInvoice?.credit_applied || 0}
                draftInvoiceSummary={selectedInvoice}
              />
            </div>
          </Panel>
        </PanelGroup>
      )}

      <ConfirmationDialog
        id="reverse-draft-confirmation"
        isOpen={reverseDialogState.isOpen}
        onClose={() => setReverseDialogState({ isOpen: false, invoiceIds: [] })}
        onConfirm={async () => {
          const invoiceIds = [...reverseDialogState.invoiceIds];
          if (invoiceIds.length === 0) {
            setReverseDialogState({ isOpen: false, invoiceIds: [] });
            return;
          }

          setIsReverseConfirming(true);
          setError(null);

          try {
            for (const invoiceId of invoiceIds) {
              await hardDeleteInvoice(invoiceId);
            }

            setSelectedInvoices(prev => {
              const next = new Set(prev);
              invoiceIds.forEach(id => next.delete(id));
              return next;
            });

            if (selectedInvoiceId && invoiceIds.includes(selectedInvoiceId)) {
              updateUrlParams({ invoiceId: null, templateId: null });
            }

            setReverseDialogState({ isOpen: false, invoiceIds: [] });
            void loadData();
            onRefreshNeeded();
          } catch (err) {
            console.error('Failed to reverse draft invoice(s):', err);
            setError(
              err instanceof Error
                ? err.message
                : t('draftsTab.errors.reverseFailed', {
                  defaultValue: 'Failed to reverse draft invoice(s). Please try again.',
                }),
            );
          } finally {
            setIsReverseConfirming(false);
          }
        }}
        title={t('draftsTab.reverseDialog.title', {
          count: reverseDialogState.invoiceIds.length,
          defaultValue:
            reverseDialogState.invoiceIds.length > 1
              ? 'Reverse Draft Invoices'
              : 'Reverse Draft Invoice',
        })}
        message={t('draftsTab.reverseDialog.message', {
          count: reverseDialogState.invoiceIds.length,
          defaultValue:
            reverseDialogState.invoiceIds.length > 1
              ? `Reversing ${reverseDialogState.invoiceIds.length} draft invoices will delete them and release any linked time entries or usage records. This action cannot be undone.`
              : 'Reversing this draft invoice will delete it and release any linked time entries or usage records. This action cannot be undone.',
        })}
        confirmLabel={t('draftsTab.reverseDialog.confirm', { defaultValue: 'Reverse Draft' })}
        cancelLabel={t('draftsTab.reverseDialog.cancel', { defaultValue: 'Cancel' })}
        isConfirming={isReverseConfirming}
      />

      <ConfirmationDialog
        id="finalize-pending-tax-confirmation"
        isOpen={taxSourceFixState.isOpen}
        onClose={() => setTaxSourceFixState({ isOpen: false, invoiceId: null, invoiceNumber: null })}
        onConfirm={handleSwitchToInternalAndFinalize}
        title={t('draftsTab.pendingTaxDialog.title', {
          defaultValue: 'Invoice awaiting external tax',
        })}
        message={t('draftsTab.pendingTaxDialog.message', {
          invoiceNumber: taxSourceFixState.invoiceNumber ?? '',
          defaultValue:
            'This invoice is set to use tax calculated by an external accounting system, but no tax has been imported yet, so it cannot be finalized. Export it to your accounting system (QuickBooks, Xero) and import the tax back to finalize with external tax — or switch this invoice to internal tax now so Alga calculates the tax and finalize it.',
        })}
        confirmLabel={t('draftsTab.pendingTaxDialog.confirm', { defaultValue: 'Switch to internal tax & finalize' })}
        cancelLabel={t('draftsTab.pendingTaxDialog.cancel', { defaultValue: 'Cancel' })}
        isConfirming={isFixingTaxSource}
      />
    </div>
  );
};

export default DraftsTab;
