'use client';
import { Suspense, useMemo } from 'react';
import { useTranslations } from 'next-intl';
import { Box, Skeleton, Stack, TextField } from '@mui/material';
import { AppButton, AppLoading, JalaliDateField } from '@/components';
import { AdminEmptyState, AdminErrorState, AdminPageHeader, AdminPager, AuditLogRow } from '@/components/admin';
import { actorLabelFrom } from '@/components/admin/AuditLogRow';
import { useAdminListState } from '@/hooks';
import { AUDIT_PAGE_SIZE } from '@/services/admin/constants';
import type { AuditFilters } from '@/services/admin/types';
import { useAuditLogs, useUserLookup } from '@/services/admin';

const EMPTY: AuditFilters = {};

function parseFilters(params: URLSearchParams): AuditFilters {
  return {
    entityType: params.get('entityType') ?? undefined,
    entityId: params.get('entityId') ?? undefined,
    from: params.get('from') ?? undefined,
    to: params.get('to') ?? undefined,
  };
}

function serializeFilters(filters: AuditFilters): Record<string, string> {
  const r: Record<string, string> = {};
  if (filters.entityType) r.entityType = filters.entityType;
  if (filters.entityId) r.entityId = filters.entityId;
  if (filters.from) r.from = filters.from;
  if (filters.to) r.to = filters.to;
  return r;
}

/**
 * Append-only audit-log viewer (f15) — a read-only, filtered, paginated table of every admin state change,
 * each row expandable to its `changed_fields` diff. There is **no** edit/delete affordance (phase §5). The
 * filter draft is committed to the query only on Apply, so typing never refetches; the applied filters +
 * page are the cache key, so switching filters/pages never refetches data already held.
 */
export default function AdminAuditPage() {
  return (
    <Suspense fallback={<AppLoading />}>
      <AdminAuditPageInner />
    </Suspense>
  );
}

function AdminAuditPageInner() {
  const t = useTranslations('admin');
  const listState = useAdminListState<AuditFilters>({ parse: parseFilters, serialize: serializeFilters, empty: EMPTY });
  const { draft, setDraft, applied, page } = listState;

  const audit = useAuditLogs(applied, page);
  const items = audit.data?.items ?? [];
  const total = audit.data?.total ?? 0;
  const pageCount = Math.max(1, Math.ceil(total / AUDIT_PAGE_SIZE));
  const from = items.length === 0 ? 0 : (page - 1) * AUDIT_PAGE_SIZE + 1;
  const to = (page - 1) * AUDIT_PAGE_SIZE + items.length;

  // Batch id→name resolve (3.2/3.6) — one request for every actor rendered on this page, never one per row.
  const actorIds = useMemo(
    () => [...new Set((audit.data?.items ?? []).map((e) => e.actorUserId).filter((id): id is number => id != null))].sort(
      (a, b) => a - b,
    ),
    [audit.data?.items],
  );
  const userLookup = useUserLookup(actorIds);

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      <AdminPageHeader title={t('audit_title')} subtitle={t('audit_subtitle')} />

      <Stack
        direction="row"
        sx={{ gap: 1.5, flexWrap: 'wrap', alignItems: 'center', p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 'var(--bal-radius-md)' }}
      >
        <TextField
          size="small"
          label={t('audit_col_entity')}
          placeholder={t('audit_entity_type_ph')}
          value={draft.entityType ?? ''}
          onChange={(e) => setDraft((d) => ({ ...d, entityType: e.target.value || undefined }))}
          sx={{ minWidth: 200 }}
        />
        <TextField
          size="small"
          label="ID"
          placeholder={t('audit_entity_id_ph')}
          value={draft.entityId ?? ''}
          onChange={(e) => setDraft((d) => ({ ...d, entityId: e.target.value || undefined }))}
          sx={{ minWidth: 120 }}
        />
        <JalaliDateField
          label={t('audit_from')}
          value={draft.from ?? null}
          onChange={(iso) => setDraft((d) => ({ ...d, from: iso }))}
          max={draft.to}
          sx={{ minWidth: 160 }}
        />
        <JalaliDateField
          label={t('audit_to')}
          value={draft.to ?? null}
          onChange={(iso) => setDraft((d) => ({ ...d, to: iso }))}
          min={draft.from}
          sx={{ minWidth: 160 }}
        />
        <AppButton variant="contained" color="primary" onClick={listState.apply}>
          {t('apply')}
        </AppButton>
        <AppButton variant="text" color="inherit" onClick={listState.clear}>
          {t('clear')}
        </AppButton>
      </Stack>

      {audit.isLoading ? (
        <Stack sx={{ gap: 1 }}>{[0, 1, 2, 3].map((k) => <Skeleton key={k} variant="rounded" height={56} />)}</Stack>
      ) : audit.isError ? (
        <AdminErrorState message={t('error_generic')} retryLabel={t('retry')} onRetry={() => audit.refetch()} />
      ) : items.length === 0 ? (
        <AdminEmptyState icon="audit" title={t('audit_empty')} />
      ) : (
        <Stack sx={{ gap: 1 }}>
          {items.map((entry) => (
            <AuditLogRow key={entry.id} entry={entry} actorLabel={actorLabelFrom(userLookup.data, entry.actorUserId)} />
          ))}
        </Stack>
      )}
      {items.length > 0 ? (
        <Box sx={{ typography: 'caption', color: 'text.secondary' }}>{t('showing_range', { from, to, total })}</Box>
      ) : null}

      <AdminPager
        page={page}
        pageCount={pageCount}
        onPrev={() => listState.goToPage(Math.max(1, page - 1))}
        onNext={() => listState.goToPage(Math.min(pageCount, page + 1))}
        prevLabel={t('prev_page')}
        nextLabel={t('next_page')}
        indicator={t('page_indicator', { page, total: pageCount })}
      />
    </Box>
  );
}
