// Admin promo-codes list — fetches codes from /api/admin/promo-codes and displays in a table.

import { useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import { useT } from '@/lib/i18n/react';
import { usePaginatedQuery } from '@/lib/hooks/usePaginatedQuery';
import { Button } from '@/components/ui/primitives/Button';
import { Badge } from '@/components/ui/primitives/Badge';
import { EmptyState } from '@/components/ui/feedback/EmptyState';
import { ErrorState } from '@/components/ui/feedback/ErrorState';
import {
  AlertDialog,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogAction,
  AlertDialogCancel,
} from '@/components/ui/overlays/AlertDialog';
import { PromoCodesListSkeleton } from '@/components/ui/feedback/Skeleton';
import { Pagination } from '@/components/ui/primitives/Pagination';
import { notify } from '@/lib/query/toast-bridge';
import { captureCaught } from '@/lib/observability';
import { Table } from '@/components/ui/primitives/Table';
import { getCsrfToken } from '@/lib/csrf';
import { formatPromoValue, promoStatusTone } from '@/lib/promo-formatters';
import { type PromoFunder } from '@/lib/enums/promo-funder';
import { type PromoKind } from '@/lib/enums/promo-kind';
import { type PromoStatus } from '@/lib/enums/promo-status';
import { HydratedIsland } from '@/components/HydratedIsland';
import { QueryBoundary } from '@platform-modules/ui-primitives';

function kindLabel(kind: PromoKind, t: (key: string) => string): string {
  if (kind === 'percentage') return t('admin.table.kind_percentage');
  if (kind === 'fixed_amount') return t('admin.table.kind_fixed_amount');
  return t('admin.table.kind_bogo');
}

function funderLabel(funder: PromoFunder, t: (key: string) => string): string {
  if (funder === 'platform') return t('admin.form.funder_platform');
  return t('admin.form.funder_vendor');
}

function statusLabel(status: PromoStatus, t: (key: string) => string): string {
  if (status === 'active') return t('admin.form.status_active');
  if (status === 'paused') return t('admin.form.status_paused');
  return t('admin.form.status_archived');
}

function formatRowValue(row: PromoRow, t: (key: string) => string): string {
  if (row.kind === 'bogo' && row.bogoBuy != null && row.bogoGetFree != null) {
    return t('admin.table.bogo_value')
      .replace('{{buy}}', String(row.bogoBuy))
      .replace('{{free}}', String(row.bogoGetFree));
  }
  return formatPromoValue(row);
}

interface PromoRow {
  id: string;
  code: string;
  kind: PromoKind;
  valueBps: number | null;
  valueAmount: number | null;
  bogoBuy: number | null;
  bogoGetFree: number | null;
  funder: PromoFunder;
  status: PromoStatus;
  redemptionCount: number;
  totalCap: number | null;
}

function PromoCodesListInner() {
  const t = useT('promo_codes') as unknown as (key: string) => string;
  const tCommon = useT('common');
  const {
    data: rows,
    totalPages,
    page,
    isInitialLoading,
    error,
    setPage,
    refetch,
  } = usePaginatedQuery<PromoRow>({
    endpoint: '/api/admin/promo-codes',
    limit: 20,
    initialData: [],
    initialTotal: 0,
    dataKey: 'codes',
  });
  const [archiving, setArchiving] = useState<string | null>(null);
  const [archiveConfirmId, setArchiveConfirmId] = useState<string | null>(null);
  const archiveTarget = rows.find((r) => r.id === archiveConfirmId) ?? null;

  const archiveMutation = useMutation({
    mutationFn: async (id: string) => {
      const res = await fetch(`/api/admin/promo-codes/${id}`, {
        method: 'DELETE',
        headers: { 'x-csrf-token': getCsrfToken() },
      });
      if (!res.ok) throw new Error('Archive failed');
    },
    onSuccess: (_data, id) => {
      refetch();
      notify.success(t('admin.archived_ok'));
      setArchiving(null);
      void id;
    },
    onError: (err) => {
      captureCaught(err, {
        scope: 'features.admin-promo-codes.PromoCodesList',
        severity: 'warning',
      });
      notify.error(t('admin.archived_error'));
      setArchiving(null);
    },
  });

  function handleArchive(id: string) {
    setArchiveConfirmId(id);
  }

  function confirmArchive() {
    if (!archiveConfirmId) return;
    setArchiving(archiveConfirmId);
    archiveMutation.mutate(archiveConfirmId);
    setArchiveConfirmId(null);
  }

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

  return (
    <QueryBoundary
      query={promoCodesQuery}
      skeleton={<PromoCodesListSkeleton />}
      errorFallback={() => (
        <ErrorState
          title={t('admin.list_error')}
          action={
            <Button variant="secondary" size="sm" onClick={() => refetch()}>
              {tCommon('retry')}
            </Button>
          }
        />
      )}
    >
      {(resolved) => (
        <div className="relative px-4 py-6">
          <div className="mb-6 flex items-center justify-end">
            <Button asChild variant="primary" size="md">
              <a href="/admin/promo-codes/new">{t('admin.new_code')}</a>
            </Button>
          </div>

          {resolved.rows.length === 0 ? (
            <EmptyState title={t('admin.empty_title')} description={t('admin.empty_desc')} />
          ) : (
            <>
              <Table className="border-border-default rounded-lg border">
                <Table.Head className="text-text-muted bg-neutral-50">
                  <Table.Row>
                    <Table.HeadCell className="px-4 py-3 font-medium">
                      {t('admin.table.code')}
                    </Table.HeadCell>
                    <Table.HeadCell className="px-4 py-3 font-medium">
                      {t('admin.table.kind')}
                    </Table.HeadCell>
                    <Table.HeadCell className="px-4 py-3 font-medium">
                      {t('admin.table.value')}
                    </Table.HeadCell>
                    <Table.HeadCell className="px-4 py-3 font-medium">
                      {t('admin.table.funder')}
                    </Table.HeadCell>
                    <Table.HeadCell className="px-4 py-3 font-medium">
                      {t('admin.table.status')}
                    </Table.HeadCell>
                    <Table.HeadCell className="px-4 py-3 font-medium">
                      {t('admin.table.redemption_count')}
                    </Table.HeadCell>
                    <Table.HeadCell className="px-4 py-3 font-medium">
                      {t('admin.table.actions')}
                    </Table.HeadCell>
                  </Table.Row>
                </Table.Head>
                <Table.Body className="bg-surface-base divide-y divide-neutral-100">
                  {resolved.rows.map((r) => (
                    <Table.Row key={r.id} className="transition-colors hover:bg-neutral-50">
                      <Table.Cell className="px-4 py-3 font-mono font-semibold tracking-wide">
                        {r.code}
                      </Table.Cell>
                      <Table.Cell className="px-4 py-3">{kindLabel(r.kind, t)}</Table.Cell>
                      <Table.Cell className="px-4 py-3">{formatRowValue(r, t)}</Table.Cell>
                      <Table.Cell className="px-4 py-3">{funderLabel(r.funder, t)}</Table.Cell>
                      <Table.Cell className="px-4 py-3">
                        <Badge tone={promoStatusTone(r.status)} size="sm">
                          {statusLabel(r.status, t)}
                        </Badge>
                      </Table.Cell>
                      <Table.Cell className="px-4 py-3">
                        {r.redemptionCount}
                        {r.totalCap != null
                          ? ` / ${r.totalCap}`
                          : ` / ${t('admin.table.unlimited')}`}
                      </Table.Cell>
                      <Table.Cell className="px-4 py-3">
                        <div className="flex items-center gap-2">
                          <Button asChild variant="ghost" size="sm">
                            <a href={`/admin/promo-codes/${r.id}`}>{t('admin.table.edit')}</a>
                          </Button>
                          {r.status !== 'archived' && (
                            <Button
                              variant="ghost"
                              size="sm"
                              disabled={archiving === r.id}
                              onClick={() => handleArchive(r.id)}
                            >
                              {t('admin.table.archive')}
                            </Button>
                          )}
                        </div>
                      </Table.Cell>
                    </Table.Row>
                  ))}
                </Table.Body>
              </Table>

              {resolved.totalPages > 1 && (
                <div className="mt-4">
                  <Pagination
                    page={resolved.page}
                    totalPages={resolved.totalPages}
                    onPageChange={setPage}
                  />
                </div>
              )}
            </>
          )}

          <AlertDialog
            open={!!archiveConfirmId}
            onOpenChange={(open) => {
              if (!open) setArchiveConfirmId(null);
            }}
          >
            <AlertDialogContent>
              <AlertDialogHeader>
                <AlertDialogTitle>{t('admin.table.archive')}</AlertDialogTitle>
                <AlertDialogDescription>
                  {archiveTarget
                    ? t('admin.confirm_archive').replace('{code}', archiveTarget.code)
                    : t('admin.confirm_archive').replace('{code}', '—')}
                </AlertDialogDescription>
              </AlertDialogHeader>
              <AlertDialogFooter>
                <AlertDialogCancel>{tCommon('cancel')}</AlertDialogCancel>
                <AlertDialogAction onClick={confirmArchive}>
                  {t('admin.table.archive')}
                </AlertDialogAction>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>
        </div>
      )}
    </QueryBoundary>
  );
}

export function PromoCodesList() {
  return (
    <HydratedIsland>
      <PromoCodesListInner />
    </HydratedIsland>
  );
}
