/**
 * Audit Log Manager — admin-only forensic view (`/dashboard/admin/audit`).
 */
import { useCallback, useMemo, useState } from 'react';
import { Navigate } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';

import { fetchAuditEvents } from '@/audit/adminAuditApi';
import type { AuditListItem, AuditListQuery } from '@/audit/types';
import { localDateTimeInputToUtcRfc3339 } from '@/audit/formatAuditTime';
import { useAuth } from '@ump/shared';

import {
  AuditLogFilters,
  type AuditFilterFormState,
} from '@/admin/audit/AuditLogFilters';
import { AuditLogTable } from '@/admin/audit/AuditLogTable';
import { AuditEventDetailSheet } from '@/admin/audit/AuditEventDetailSheet';

const PAGE_SIZE = 50;

function localInputSlice(d: Date): string {
  return new Date(d.getTime() - d.getTimezoneOffset() * 60_000).toISOString().slice(0, 16);
}

function emptyForm(now: Date, from: Date): AuditFilterFormState {
  return {
    fromLocal: localInputSlice(from),
    toLocal: localInputSlice(now),
    actorEmail: '',
    actorUserId: '',
    entityType: '',
    entityId: '',
    action: '',
  };
}

export function AuditLogManagerPage() {
  const { hasPermission, loading } = useAuth();
  const [page, setPage] = useState(1);

  const [draft, setDraft] = useState<AuditFilterFormState>(() =>
    emptyForm(new Date(), new Date(Date.now() - 7 * 86_400_000)),
  );

  /** Last-applied snapshot for query key (Áp dụng bộ lọc commits draft → applied). */
  const [applied, setApplied] = useState<AuditFilterFormState>(() =>
    emptyForm(new Date(), new Date(Date.now() - 7 * 86_400_000)),
  );

  const appliedQueryKey = useMemo(() => ({ ...applied, page }), [applied, page]);

  const listQueryBody = useCallback((): AuditListQuery => {
    const q: AuditListQuery = {
      page,
      page_size: PAGE_SIZE,
      sort: 'occurred_at:desc',
    };
    const fromIso = localDateTimeInputToUtcRfc3339(applied.fromLocal);
    const toIso = localDateTimeInputToUtcRfc3339(applied.toLocal);
    if (fromIso) q.from = fromIso;
    if (toIso) q.to = toIso;
    if (applied.actorEmail.trim()) q.actor_email = applied.actorEmail.trim().toLowerCase();
    if (applied.actorUserId.trim()) q.actor_user_id = applied.actorUserId.trim();
    if (applied.entityType.trim()) q.entity_type = applied.entityType.trim();
    if (applied.entityId.trim()) q.entity_id = applied.entityId.trim();
    if (applied.action.trim()) q.action = applied.action.trim();
    return q;
  }, [applied, page]);

  const auditQuery = useQuery({
    queryKey: ['admin-audit-events', appliedQueryKey],
    queryFn: () => fetchAuditEvents(listQueryBody()),
  });

  const [sheetOpen, setSheetOpen] = useState(false);
  const [selected, setSelected] = useState<AuditListItem | null>(null);

  const presetRange = useCallback((ms: number) => {
    const now = new Date();
    const from = new Date(now.getTime() - ms);
    setDraft(emptyForm(now, from));
    setApplied(emptyForm(now, from));
    setPage(1);
  }, []);

  const onApplyFilters = () => {
    setApplied(draft);
    setPage(1);
  };

  if (!loading && !hasPermission('admin.access')) {
    return <Navigate to="/unauthorized" replace />;
  }

  const items = auditQuery.data?.items ?? [];

  return (
    <div className="mx-auto max-w-7xl space-y-6 animate-fade-in">
      <header className="space-y-1">
        <h1 className="text-3xl font-bold tracking-tight">Nhật ký thao tác (Audit)</h1>
        <p className="text-muted-foreground text-sm max-w-3xl">
          Theo dõi CRUD và đăng nhập của người nộp đơn và quản trị trên các thực thể đã được gắn
          instrumentation (PostgreSQL{' '}
          <code className="text-xs bg-muted px-1 rounded">audit_events</code>, MinIO thông qua{' '}
          <code className="text-xs bg-muted px-1 rounded">application_evidence</code> payload).
          Chênh lệch JSON được tính trên trình duyệt.
        </p>
      </header>

      <AuditLogFilters
        value={draft}
        onChange={(patch) => setDraft((prev) => ({ ...prev, ...patch }))}
        onApply={onApplyFilters}
        onPreset24h={() => presetRange(86_400_000)}
        onPreset7d={() => presetRange(7 * 86_400_000)}
        onPreset30d={() => presetRange(30 * 86_400_000)}
      />

      <AuditLogTable
        items={items}
        onSelect={(row) => {
          setSelected(row);
          setSheetOpen(true);
        }}
        page={page}
        total={auditQuery.data?.total ?? 0}
        pageSize={PAGE_SIZE}
        loading={auditQuery.isLoading}
        onPrev={() => setPage((p) => Math.max(1, p - 1))}
        onNext={() => setPage((p) => p + 1)}
      />

      {auditQuery.error && (
        <p className="text-sm text-destructive">
          Không tải được audit: {String((auditQuery.error as Error)?.message ?? auditQuery.error)}
        </p>
      )}

      <AuditEventDetailSheet open={sheetOpen} onOpenChange={setSheetOpen} summary={selected} />
    </div>
  );
}
