// src/features/admin-outbox/OutboxMonitor.tsx
// Admin: Outbox Event Monitor - paginated list with status filter and retry action.

'use client';

import { useState } from 'react';
import { getCsrfToken } from '@/lib/csrf';
import { useT, useLocale } from '@/lib/i18n/react';
import { formatDateTime } from '@/lib/format';
import { usePaginatedQuery } from '@/lib/hooks/usePaginatedQuery';
import { Button } from '@/components/ui/primitives/Button';
import { Badge } from '@/components/ui/primitives/Badge';
import { Stack } from '@/components/ui/layout/Stack';
import { Row } from '@/components/ui/layout/Row';
import { PageHeader } from '@/components/ui/layout/PageHeader';
import { Pagination } from '@/components/ui/primitives/Pagination';
import { EmptyState } from '@/components/ui/feedback/EmptyState';
import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
} from '@/components/ui/primitives/Select';
import { Label } from '@/components/ui/primitives/Label';
import type { OutboxEventRow } from '@/server/admin/resources/outbox/types';
import { captureCaught } from '@/lib/observability';

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

export interface OutboxMonitorProps {
  initialEvents: OutboxEventRow[];
  initialTotal: number;
  initialPage?: number;
}

type StatusFilter = '' | 'pending' | 'processed' | 'failed' | 'abandoned';

const STATUS_TONE: Record<string, 'neutral' | 'success' | 'warning' | 'danger'> = {
  pending: 'neutral',
  processed: 'success',
  failed: 'warning',
  abandoned: 'danger',
};

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

export function OutboxMonitor({ initialEvents, initialTotal, initialPage }: OutboxMonitorProps) {
  const t = useT('admin_outbox');
  const { locale } = useLocale();
  const tCommon = useT('common');

  const [statusFilter, setStatusFilter] = useState<StatusFilter>('');
  const [retryingId, setRetryingId] = useState<string | null>(null);
  const [retryError, setRetryError] = useState<string | null>(null);

  const params: Record<string, string> = {};
  if (statusFilter) params.status = statusFilter;

  const { data, total, totalPages, page, isLoading, error, setPage, refetch } =
    usePaginatedQuery<OutboxEventRow>({
      endpoint: '/api/admin/outbox',
      params,
      limit: 20,
      initialData: initialEvents,
      initialTotal,
      initialPage,
      dataKey: 'events',
    });

  async function handleRetry(eventId: string) {
    setRetryingId(eventId);
    setRetryError(null);
    try {
      const res = await fetch(`/api/admin/outbox/${eventId}/retry`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
      });
      if (!res.ok) {
        const body = (await res.json().catch((err) => {
          captureCaught(err, { scope: 'features.admin-outbox.OutboxMonitor', severity: 'info' });
          return {};
        })) as Record<string, unknown>;
        throw new Error((body.error as string) || `HTTP ${res.status}`);
      }
      refetch();
    } catch (err) {
      setRetryError(err instanceof Error ? err.message : String(err));
    } finally {
      setRetryingId(null);
    }
  }

  return (
    <Stack gap="6" as="section" aria-label={t('title')}>
      <PageHeader title={t('title')} />

      {/* Filters */}
      <Row gap="3" wrap>
        <div>
          <Label htmlFor="outbox-status-filter">{t('filter_status')}</Label>
          <Select
            value={statusFilter || '__all__'}
            onValueChange={(v) => setStatusFilter((v === '__all__' ? '' : v) as StatusFilter)}
          >
            <SelectTrigger id="outbox-status-filter" className="w-44">
              <SelectValue placeholder={t('filter_status')} />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="__all__">{t('filter_all')}</SelectItem>
              <SelectItem value="pending">{t('status_pending')}</SelectItem>
              <SelectItem value="processed">{t('status_processed')}</SelectItem>
              <SelectItem value="failed">{t('status_failed')}</SelectItem>
              <SelectItem value="abandoned">{t('status_abandoned')}</SelectItem>
            </SelectContent>
          </Select>
        </div>
      </Row>

      {/* Errors */}
      {error && (
        <p role="alert" className="text-danger-600 text-sm">
          {error}
        </p>
      )}
      {retryError && (
        <p role="alert" className="text-danger-600 text-sm">
          {retryError}
        </p>
      )}

      {/* List */}
      {isLoading ? (
        <p className="text-text-secondary py-8 text-center text-sm">{tCommon('loading')}</p>
      ) : data.length === 0 ? (
        <EmptyState title={t('no_events')} className="py-8" />
      ) : (
        <Stack gap="3" as="ul">
          {data.map((event) => (
            <li key={event.id} className="bg-surface-default rounded-2xl p-4 shadow-md">
              <Stack gap="2">
                <Row justify="between" align="start" wrap>
                  <Stack gap="1" className="min-w-0 flex-1">
                    {/* Event type + aggregate */}
                    <Row gap="2" align="center">
                      <Badge tone={STATUS_TONE[event.status] ?? 'neutral'} size="sm">
                        {t(`status_${event.status}`)}
                      </Badge>
                      <p className="text-text-primary text-sm font-semibold" data-diag="">
                        {event.eventType}
                      </p>
                    </Row>
                    <p className="text-text-secondary text-xs" data-diag="">
                      {event.aggregateType} · {event.aggregateId}
                    </p>

                    {/* Retry count + last error */}
                    <Row gap="3">
                      <span className="text-text-secondary text-xs">
                        {t('retry_count_label')}: {event.retryCount}
                      </span>
                      {event.lastError && (
                        <span
                          className="text-danger-600 max-w-xs truncate text-xs"
                          title={event.lastError}
                        >
                          {event.lastError}
                        </span>
                      )}
                    </Row>

                    {/* Timestamps */}
                    <Row gap="3" wrap>
                      <span className="text-text-secondary text-xs">
                        {t('created_at_label')}: {formatDateTime(event.createdAt, locale)}
                      </span>
                      {event.processedAt && (
                        <span className="text-success-600 text-xs">
                          {t('processed_at_label')}:{' '}
                          {formatDateTime(event.processedAt, locale)}
                        </span>
                      )}
                      {event.failedAt && !event.processedAt && (
                        <span className="text-warning-600 text-xs">
                          {t('failed_at_label')}: {formatDateTime(event.failedAt, locale)}
                        </span>
                      )}
                    </Row>
                  </Stack>

                  {/* Retry action - only for failed or abandoned events */}
                  {(event.status === 'failed' || event.status === 'abandoned') && (
                    <Button
                      variant="secondary"
                      size="sm"
                      loading={retryingId === event.id}
                      disabled={retryingId !== null}
                      onClick={() => handleRetry(event.id)}
                    >
                      {t('retry')}
                    </Button>
                  )}
                </Row>
              </Stack>
            </li>
          ))}
        </Stack>
      )}

      {/* Pagination */}
      <Pagination
        page={page}
        totalPages={totalPages}
        onPageChange={setPage}
        isLoading={isLoading}
      />

      {/* Total count */}
      <p className="text-text-secondary text-center text-xs">
        {total} {t('total_label')}
      </p>
    </Stack>
  );
}
