// src/features/admin-settlement/SettlementOversight.tsx
// Admin: settlement oversight list with mark-paid action + Stripe drill-down.

'use client';

import { useState, useId } from 'react';
import { usePaginatedQuery } from '@/lib/hooks/usePaginatedQuery';
import { useT, useLocale } from '@/lib/i18n/react';
import { formatDate } from '@/lib/format';
import { formatAgorotLocale } from '@/lib/money';
import { getCsrfToken } from '@/lib/csrf';
import { captureCaught } from '@/lib/observability';
import { AdminListPage } from '@/components/ui/domain/admin/AdminListPage';
import { AdminTable, type ColumnDef } from '@/components/ui/domain/admin/AdminTable';
import { Pagination } from '@/components/ui/primitives/Pagination';
import { ErrorBoundary } from '@/components/ui/feedback/ErrorBoundary';
import { ErrorState } from '@/components/ui/feedback/ErrorState';
import { AdminListPageSkeleton } from '@/components/ui/feedback/Skeleton';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/overlays/Dialog';
import { Button } from '@/components/ui/primitives/Button';
import { Pill } from '@/components/ui/primitives/Pill';
import { Label } from '@/components/ui/primitives/Label';
import { Textarea } from '@/components/ui/primitives/Textarea';
import {
  TooltipProvider,
  Tooltip,
  TooltipTrigger,
  TooltipContent,
} from '@/components/ui/overlays/Tooltip';
import { StripeAdminDrilldown } from './StripeAdminDrilldown';
import { HydratedIsland } from '@/components/HydratedIsland';
import { QueryBoundary } from '@platform-modules/ui-primitives';

// ─── Types ────────────────────────────────────────────────────────────────────

export interface SettlementRow {
  id: string;
  vendorId: string;
  vendorBusinessName: string;
  periodLabel: string;
  totalAgorot: number;
  vendorAmountAgorot: number;
  platformFeeAgorot: number;
  status: string;
  createdAt: string;
}

export interface SettlementOversightProps {
  initialRows: SettlementRow[];
  initialTotal: number;
  initialPage?: number;
  stripePublishableKey?: string;
}

// ─── Status tone map ──────────────────────────────────────────────────────────

const STATUS_TONE: Record<string, 'warning' | 'success' | 'danger' | 'neutral'> = {
  pending: 'warning',
  paid: 'success',
  disputed: 'danger',
  cancelled: 'neutral',
};

// ─── Component ────────────────────────────────────────────────────────────────

function SettlementOversightInner({
  initialRows,
  initialTotal,
  initialPage,
  stripePublishableKey,
}: SettlementOversightProps) {
  const t = useT('admin_settlements');
  const tList = useT('admin_list');
  const { locale } = useLocale();
  const notesLabelId = useId();

  const { data, totalPages, page, isInitialLoading, isRefetching, error, setPage, refetch } =
    usePaginatedQuery<SettlementRow>({
      endpoint: '/api/admin/settlements',
      params: {},
      limit: 20,
      initialData: initialRows,
      initialTotal,
      initialPage,
      dataKey: 'settlements',
    });

  // Action state
  const [actionLoading, setActionLoading] = useState<string | null>(null);
  const [actionError, setActionError] = useState<string | null>(null);

  // Mark-paid dialog
  const [markPaidDialog, setMarkPaidDialog] = useState<SettlementRow | null>(null);
  const [markPaidNotes, setMarkPaidNotes] = useState('');

  // Stripe drill-down
  const [stripeDrilldown, setStripeDrilldown] = useState<SettlementRow | null>(null);

  // Reconcile state
  const [reconcileLoading, setReconcileLoading] = useState(false);
  const [reconcileResult, setReconcileResult] = useState<string | null>(null);

  // ── Handlers ──────────────────────────────────────────────────────────────

  function openMarkPaid(row: SettlementRow) {
    setMarkPaidNotes('');
    setActionError(null);
    setMarkPaidDialog(row);
  }

  function closeMarkPaid() {
    setMarkPaidDialog(null);
    setMarkPaidNotes('');
  }

  async function handleMarkPaid() {
    if (!markPaidDialog) return;
    const [vendorId, periodMonth] = markPaidDialog.id.split(':');
    setActionLoading(markPaidDialog.id);
    setActionError(null);
    try {
      const res = await fetch('/api/admin/settlements/mark-paid', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-csrf-token': getCsrfToken(),
        },
        body: JSON.stringify({ vendorId, periodMonth, notes: markPaidNotes || undefined }),
      });
      if (!res.ok) {
        const json = (await res.json().catch((err) => {
          captureCaught(err, { scope: 'SettlementOversight.markPaid.parse' });
          return {};
        })) as Record<string, unknown>;
        throw new Error((json.error as string) || `HTTP ${res.status}`);
      }
      closeMarkPaid();
      refetch();
    } catch (err) {
      captureCaught(err instanceof Error ? err : new Error(String(err)), {
        scope: 'SettlementOversight.markPaid',
      });
      setActionError(err instanceof Error ? err.message : t('mark_error'));
    } finally {
      setActionLoading(null);
    }
  }

  async function handleReconcile() {
    setReconcileLoading(true);
    setReconcileResult(null);
    setActionError(null);
    try {
      const res = await fetch('/api/admin/reconcile', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-csrf-token': getCsrfToken(),
        },
      });
      const json = (await res.json()) as Record<string, unknown>;
      if (!res.ok) throw new Error((json.error as string) || `HTTP ${res.status}`);
      const msg = t('reconcile_success')
        .replace('{checked}', String(json.checked))
        .replace('{resolved}', String(json.resolved))
        .replace('{failed}', String(json.failed));
      setReconcileResult(msg);
      refetch();
    } catch (err) {
      captureCaught(err instanceof Error ? err : new Error(String(err)), {
        scope: 'SettlementOversight.reconcile',
      });
      setActionError(err instanceof Error ? err.message : t('reconcile_error'));
    } finally {
      setReconcileLoading(false);
    }
  }

  // ── Columns ───────────────────────────────────────────────────────────────

  const columns: ColumnDef<SettlementRow>[] = [
    {
      key: 'vendorBusinessName',
      label: t('col_vendor'),
      render: (row) => (
        <a
          href={`/admin/vendors/${row.vendorId}`}
          className="text-[var(--color-text-primary)] hover:underline"
          data-user-displayname
        >
          {row.vendorBusinessName}
        </a>
      ),
    },
    { key: 'periodLabel', label: t('col_period'), align: 'center' },
    {
      key: 'status',
      label: t('col_status'),
      align: 'center',
      render: (row) => {
        const statusLabel = t(`status_${row.status}` as Parameters<typeof t>[0]);
        const pill = (
          <Pill tone={STATUS_TONE[row.status] ?? 'neutral'} size="sm">
            {statusLabel}
          </Pill>
        );
        if (row.status === 'pending') {
          return (
            <Tooltip>
              <TooltipTrigger asChild>
                <span className="inline-flex cursor-help">{pill}</span>
              </TooltipTrigger>
              <TooltipContent side="top" className="max-w-xs text-wrap">
                {t('tooltip_status_pending')}
              </TooltipContent>
            </Tooltip>
          );
        }
        return pill;
      },
    },
    {
      key: 'totalAgorot',
      label: t('col_total'),
      align: 'end',
      render: (row) => formatAgorotLocale(row.totalAgorot, locale),
    },
    {
      key: 'vendorAmountAgorot',
      label: t('col_vendor_amount'),
      align: 'end',
      headerTooltip: t('tooltip_col_vendor_amount'),
      render: (row) => formatAgorotLocale(row.vendorAmountAgorot, locale),
    },
    {
      key: 'platformFeeAgorot',
      label: t('col_platform_fee'),
      align: 'end',
      render: (row) => formatAgorotLocale(row.platformFeeAgorot, locale),
    },
    {
      key: 'createdAt',
      label: t('col_created'),
      align: 'center',
      render: (row) => formatDate(row.createdAt, locale),
    },
    {
      key: 'id',
      label: t('col_actions'),
      align: 'center',
      render: (row) => {
        const busy = actionLoading === row.id;
        return (
          <div className="flex items-center justify-center gap-2">
            {row.status === 'pending' && (
              <Button
                variant="primary"
                size="sm"
                loading={busy}
                disabled={!!actionLoading && !busy}
                onClick={() => openMarkPaid(row)}
              >
                {t('btn_mark_paid')}
              </Button>
            )}
            {stripePublishableKey && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant="ghost"
                    size="sm"
                    disabled={!!actionLoading}
                    onClick={() => setStripeDrilldown(row)}
                  >
                    {t('btn_stripe_details')}
                  </Button>
                </TooltipTrigger>
                <TooltipContent side="top" className="max-w-xs text-wrap">
                  {t('tooltip_btn_stripe_details')}
                </TooltipContent>
              </Tooltip>
            )}
          </div>
        );
      },
    },
  ];

  // ── Render ────────────────────────────────────────────────────────────────

  const settlementsQuery = {
    data: isInitialLoading ? undefined : { rows: data, totalPages, page },
    isLoading: isInitialLoading,
    isPending: isInitialLoading,
    isError: Boolean(error),
    error: error ? new Error(error) : null,
    refetch,
  };

  return (
    <ErrorBoundary>
      <TooltipProvider delayDuration={200}>
        <div className="mb-4 flex items-center gap-3">
          <Tooltip>
            <TooltipTrigger asChild>
              <Button
                variant="secondary"
                size="sm"
                loading={reconcileLoading}
                disabled={reconcileLoading}
                onClick={() => void handleReconcile()}
              >
                {reconcileLoading ? t('reconcile_running') : t('btn_reconcile')}
              </Button>
            </TooltipTrigger>
            <TooltipContent side="bottom" className="max-w-xs text-wrap">
              {t('btn_reconcile_tooltip')}
            </TooltipContent>
          </Tooltip>
          {reconcileResult && <p className="text-success-700 text-sm">{reconcileResult}</p>}
        </div>
        {actionError && (
          <p role="alert" className="text-danger-600 mb-4 text-sm">
            {actionError}
          </p>
        )}

        <QueryBoundary
          query={settlementsQuery}
          skeleton={<AdminListPageSkeleton showFilterBar={false} tableCols={8} />}
          errorFallback={() => (
            <ErrorState
              title={tList('error_title')}
              action={
                <Button variant="secondary" size="sm" onClick={() => refetch()}>
                  {tList('retry')}
                </Button>
              }
            />
          )}
        >
          {(resolved) => (
            <AdminListPage
              subtitle={t('page_subtitle')}
              busy={isRefetching}
              table={<AdminTable<SettlementRow> columns={columns} rows={resolved.rows} />}
              pagination={
                <Pagination
                  page={resolved.page}
                  totalPages={resolved.totalPages}
                  onPageChange={setPage}
                />
              }
            />
          )}
        </QueryBoundary>

        {/* Mark Paid dialog */}
        <Dialog
          open={!!markPaidDialog}
          onOpenChange={(open) => {
            if (!open) closeMarkPaid();
          }}
        >
          <DialogContent>
            <DialogHeader>
              <DialogTitle>{t('mark_paid_dialog_title')}</DialogTitle>
            </DialogHeader>

            <div className="flex flex-col gap-4 py-2">
              {markPaidDialog && (
                <p className="text-body-sm">
                  {markPaidDialog.vendorBusinessName} — {markPaidDialog.periodLabel}
                </p>
              )}

              <div className="flex flex-col gap-1">
                <Label htmlFor={notesLabelId}>{t('mark_paid_dialog_notes_label')}</Label>
                <Textarea
                  id={notesLabelId}
                  rows={3}
                  value={markPaidNotes}
                  onChange={(e) => setMarkPaidNotes(e.target.value)}
                />
              </div>

              {actionError && (
                <p role="alert" className="text-danger-600 text-sm">
                  {actionError}
                </p>
              )}

              <p className="text-text-secondary text-sm">{t('mark_paid_dialog_note')}</p>
            </div>

            <DialogFooter>
              <Button variant="ghost" onClick={closeMarkPaid}>
                {t('mark_paid_dialog_cancel')}
              </Button>
              <Button
                variant="primary"
                loading={!!actionLoading}
                onClick={() => void handleMarkPaid()}
              >
                {t('mark_paid_dialog_confirm')}
              </Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>

        {/* Stripe drill-down overlay */}
        {stripeDrilldown && stripePublishableKey && (
          <StripeAdminDrilldown
            vendorId={stripeDrilldown.vendorId}
            vendorName={stripeDrilldown.vendorBusinessName}
            publishableKey={stripePublishableKey}
            onClose={() => setStripeDrilldown(null)}
          />
        )}
      </TooltipProvider>
    </ErrorBoundary>
  );
}

export function SettlementOversight({
  initialRows,
  initialTotal,
  initialPage,
  stripePublishableKey,
}: SettlementOversightProps) {
  return (
    <HydratedIsland>
      <SettlementOversightInner
        initialRows={initialRows}
        initialTotal={initialTotal}
        initialPage={initialPage}
        stripePublishableKey={stripePublishableKey}
      />
    </HydratedIsland>
  );
}
