import * as React from 'react';
import type { AuditEvent, AuditAction, AuditOutcome } from '@sentryagent/idp-sdk';
import { Badge } from '@/components/ui/badge';
import { getClient } from '@/lib/client';

const PAGE_LIMIT = 20;

/** All AuditAction values for the filter dropdown. */
const AUDIT_ACTIONS: AuditAction[] = [
  'agent.created',
  'agent.updated',
  'agent.decommissioned',
  'agent.suspended',
  'agent.reactivated',
  'token.issued',
  'token.revoked',
  'token.introspected',
  'credential.generated',
  'credential.rotated',
  'credential.revoked',
  'auth.failed',
];

/** Formats an ISO timestamp to a readable local date-time string. */
function formatDateTime(iso: string): string {
  return new Date(iso).toLocaleString(undefined, {
    year: 'numeric', month: 'short', day: 'numeric',
    hour: '2-digit', minute: '2-digit', second: '2-digit',
  });
}

/** Truncates a string to a maximum length with ellipsis. */
function truncate(value: string, maxLen = 24): string {
  return value.length > maxLen ? `${value.slice(0, maxLen)}…` : value;
}

/**
 * Audit Log page — displays audit events with filters for agent, action, outcome, and date range.
 * Route: /dashboard/audit
 */
export default function AuditLog(): React.JSX.Element {
  const [events, setEvents] = React.useState<AuditEvent[]>([]);
  const [total, setTotal] = React.useState<number>(0);
  const [page, setPage] = React.useState<number>(1);
  const [loading, setLoading] = React.useState<boolean>(false);
  const [error, setError] = React.useState<string | null>(null);

  // Filters
  const [agentIdFilter, setAgentIdFilter] = React.useState<string>('');
  const [actionFilter, setActionFilter] = React.useState<AuditAction | ''>('');
  const [outcomeFilter, setOutcomeFilter] = React.useState<AuditOutcome | ''>('');
  const [fromDate, setFromDate] = React.useState<string>('');
  const [toDate, setToDate] = React.useState<string>('');

  // Reset to page 1 on filter change
  React.useEffect(() => {
    setPage(1);
  }, [agentIdFilter, actionFilter, outcomeFilter, fromDate, toDate]);

  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setError(null);

    const fetchEvents = async (): Promise<void> => {
      try {
        const result = await getClient().audit.queryAuditLog({
          page,
          limit: PAGE_LIMIT,
          agentId: agentIdFilter.trim() || undefined,
          action: actionFilter !== '' ? actionFilter : undefined,
          outcome: outcomeFilter !== '' ? outcomeFilter : undefined,
          fromDate: fromDate || undefined,
          toDate: toDate || undefined,
        });
        if (!cancelled) {
          setEvents(result.data);
          setTotal(result.total);
        }
      } catch (err) {
        if (!cancelled) {
          setError(err instanceof Error ? err.message : 'Failed to load audit log.');
        }
      } finally {
        if (!cancelled) setLoading(false);
      }
    };

    void fetchEvents();
    return () => { cancelled = true; };
  }, [page, agentIdFilter, actionFilter, outcomeFilter, fromDate, toDate]);

  const totalPages = Math.max(1, Math.ceil(total / PAGE_LIMIT));

  return (
    <div>
      <h1 className="mb-6 text-2xl font-bold text-slate-900">Audit Log</h1>

      {/* Filters */}
      <div className="mb-6 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-5">
        <input
          type="text"
          value={agentIdFilter}
          onChange={(e) => { setAgentIdFilter(e.target.value); }}
          placeholder="Agent ID…"
          className="rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-brand-500 focus:outline-none focus:ring-1 focus:ring-brand-500"
        />
        <select
          value={actionFilter}
          onChange={(e) => { setActionFilter(e.target.value as AuditAction | ''); }}
          className="rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-brand-500 focus:outline-none focus:ring-1 focus:ring-brand-500"
        >
          <option value="">All Actions</option>
          {AUDIT_ACTIONS.map((action) => (
            <option key={action} value={action}>{action}</option>
          ))}
        </select>
        <select
          value={outcomeFilter}
          onChange={(e) => { setOutcomeFilter(e.target.value as AuditOutcome | ''); }}
          className="rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-brand-500 focus:outline-none focus:ring-1 focus:ring-brand-500"
        >
          <option value="">All Outcomes</option>
          <option value="success">Success</option>
          <option value="failure">Failure</option>
        </select>
        <input
          type="date"
          value={fromDate}
          onChange={(e) => { setFromDate(e.target.value); }}
          className="rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-brand-500 focus:outline-none focus:ring-1 focus:ring-brand-500"
          title="From date"
        />
        <input
          type="date"
          value={toDate}
          onChange={(e) => { setToDate(e.target.value); }}
          className="rounded-md border border-slate-300 px-3 py-2 text-sm focus:border-brand-500 focus:outline-none focus:ring-1 focus:ring-brand-500"
          title="To date"
        />
      </div>

      {error && (
        <div className="mb-4 rounded-md bg-red-50 px-4 py-3 text-sm text-red-700" role="alert">
          {error}
        </div>
      )}

      <div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
        <table className="min-w-full divide-y divide-slate-200 text-sm">
          <thead className="bg-slate-50">
            <tr>
              {['Timestamp', 'Agent ID', 'Action', 'Outcome', 'IP Address'].map((col) => (
                <th key={col} className="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">
                  {col}
                </th>
              ))}
            </tr>
          </thead>
          <tbody className="divide-y divide-slate-100">
            {loading
              ? Array.from({ length: 5 }).map((_, i) => (
                <tr key={i}>
                  {Array.from({ length: 5 }).map((__, j) => (
                    <td key={j} className="px-4 py-3">
                      <div className="h-4 w-full animate-pulse rounded bg-slate-200" />
                    </td>
                  ))}
                </tr>
              ))
              : events.length === 0
              ? (
                <tr>
                  <td colSpan={5} className="px-4 py-12 text-center text-slate-400">
                    No audit events found.
                  </td>
                </tr>
              )
              : events.map((event) => (
                <tr key={event.eventId} className="hover:bg-slate-50">
                  <td className="px-4 py-3 text-slate-500 whitespace-nowrap">{formatDateTime(event.timestamp)}</td>
                  <td className="px-4 py-3 font-mono text-xs text-slate-700">{truncate(event.agentId)}</td>
                  <td className="px-4 py-3 text-slate-700">{event.action}</td>
                  <td className="px-4 py-3">
                    <Badge variant={event.outcome === 'success' ? 'success' : 'danger'}>
                      {event.outcome}
                    </Badge>
                  </td>
                  <td className="px-4 py-3 text-slate-500">{event.ipAddress}</td>
                </tr>
              ))
            }
          </tbody>
        </table>
      </div>

      {/* Pagination */}
      {!loading && total > 0 && (
        <div className="mt-4 flex items-center justify-between text-sm text-slate-600">
          <span>
            Page {page} of {totalPages} ({total} total)
          </span>
          <div className="flex gap-2">
            <button
              onClick={() => { setPage((p) => Math.max(1, p - 1)); }}
              disabled={page <= 1}
              className="rounded-md border border-slate-300 px-3 py-1.5 hover:bg-slate-50 disabled:opacity-40"
            >
              Previous
            </button>
            <button
              onClick={() => { setPage((p) => Math.min(totalPages, p + 1)); }}
              disabled={page >= totalPages}
              className="rounded-md border border-slate-300 px-3 py-1.5 hover:bg-slate-50 disabled:opacity-40"
            >
              Next
            </button>
          </div>
        </div>
      )}
    </div>
  );
}
