import { useCallback } from 'react';
import { Link, useNavigate, useSearchParams } from 'react-router';
import { ConnectionSection } from './ConnectionSection';
import { CustomersListView } from './CustomersListView';
import { DashboardView } from './DashboardView';
import { DocumentEditor } from './DocumentEditor';
import { EstimatesListView } from './EstimatesListView';
import { ExpensesListView } from './ExpensesListView';
import { InvoicesListView } from './InvoicesListView';
import { ItemsListView } from './ItemsListView';
import { PaymentsListView } from './PaymentsListView';
import { RecurringListView } from './RecurringListView';
import { ReportsView } from './ReportsView';
import { CustomerEditor, ExpenseEditor, ItemEditor, PaymentEditor } from './RecordEditors';
import { invoicesNewPaymentPath, invoicesSectionPath } from './shared';
import { useInvoiceShelfHealth } from './useInvoiceShelfData';
import { useInvoicesSection } from './useInvoicesSection';

// Right panel of the /invoices workspace: renders the section named by the URL, and owns the one piece of
// state the sections share — which record is being edited.
//
// That lives in the query string (`?edit=42`, `?edit=new`) rather than in component state, for the same
// reason selection does: it is addressable. Back closes the editor instead of leaving the screen, a
// half-written form survives a reload of the tab, and "record a payment against invoice 12" is a link
// (`?edit=new&pay=12`) rather than a click path.

type EditTarget = number | 'new' | null;

const parseEdit = (raw: string | null): EditTarget => {
  if (raw === 'new') return 'new';
  const n = Number(raw);
  return Number.isInteger(n) && n > 0 ? n : null;
};

export const InvoicesView = () => {
  const section = useInvoicesSection();
  const { data: health, isLoading: healthLoading } = useInvoiceShelfHealth();
  const [params, setParams] = useSearchParams();
  const navigate = useNavigate();

  const edit = parseEdit(params.get('edit'));
  const payFor = Number(params.get('pay')) || null;

  const openEditor = useCallback(
    (id: number | 'new', extra?: Record<string, string>) =>
      setParams(
        (prev) => {
          const next = new URLSearchParams(prev);
          next.set('edit', String(id));
          for (const [key, value] of Object.entries(extra ?? {})) next.set(key, value);
          return next;
        },
        { replace: false },
      ),
    [setParams],
  );

  const closeEditor = useCallback(
    () =>
      setParams(
        (prev) => {
          const next = new URLSearchParams(prev);
          next.delete('edit');
          next.delete('pay');
          return next;
        },
        { replace: true },
      ),
    [setParams],
  );

  // Health gates every section, and its two failure modes are answered differently: nothing configured yet is
  // the setup form, whatever section was asked for, because there is nothing else useful to show; a stored
  // instance that is failing keeps its own message and a way back, since replacing a working token by
  // accident is worse than a wall of text.
  if (section === 'settings') return <ConnectionSection />;

  if (!healthLoading && health && !health.ok) {
    if (health.configured === false) return <ConnectionSection />;

    return (
      <div className="flex h-full flex-col items-center justify-center gap-1 p-6 text-center">
        <p className="text-sm font-medium">InvoiceShelf is not answering</p>
        <p className="max-w-sm text-xs text-muted-foreground">
          {health.error ?? 'The invoiceshelf sidecar could not reach the configured instance.'}
        </p>
        <Link to={invoicesSectionPath('settings')} className="mt-2 text-xs font-medium text-primary hover:underline">
          Check the connection
        </Link>
      </div>
    );
  }

  // Documents get a full-height editor rather than a dialog — a line-item table does not fit in one, and
  // upstream gives them a whole page too.
  if (edit != null && (section === 'invoices' || section === 'estimates' || section === 'recurring')) {
    const resource = section === 'recurring' ? 'recurring-invoices' : section;
    return <DocumentEditor resource={resource} id={edit} onClose={closeEditor} />;
  }

  switch (section) {
    case 'invoices':
      return <InvoicesListView onEdit={openEditor} recordPaymentHref={invoicesNewPaymentPath} />;

    case 'estimates':
      return (
        <EstimatesListView
          onEdit={openEditor}
          onConverted={(invoiceId) => navigate(`/invoices/invoices?selected=${invoiceId}`)}
        />
      );

    case 'recurring':
      return <RecurringListView onEdit={openEditor} />;

    case 'payments':
      return (
        <>
          <PaymentsListView onEdit={openEditor} />
          {edit != null && <PaymentEditor id={edit} forInvoiceId={payFor ?? undefined} onClose={closeEditor} />}
        </>
      );

    case 'expenses':
      return (
        <>
          <ExpensesListView onEdit={openEditor} />
          {edit != null && <ExpenseEditor id={edit} onClose={closeEditor} />}
        </>
      );

    case 'customers':
      return (
        <>
          <CustomersListView onEdit={openEditor} />
          {edit != null && <CustomerEditor id={edit} onClose={closeEditor} />}
        </>
      );

    case 'items':
      return (
        <>
          <ItemsListView onEdit={openEditor} />
          {edit != null && <ItemEditor id={edit} onClose={closeEditor} />}
        </>
      );

    case 'reports':
      return <ReportsView />;

    default:
      return <DashboardView />;
  }
};
