import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
import type { SshAuditRow } from '../../lib/ssh-types';

interface Filters {
  action: string;
  ownerId: string;
  connectionId: string;
  outcome: string;
  limit: number;
}

async function fetchAudit(filters: Filters): Promise<SshAuditRow[]> {
  const params = new URLSearchParams();
  if (filters.action) params.set('action', filters.action);
  if (filters.ownerId) params.set('ownerId', filters.ownerId);
  if (filters.connectionId) params.set('connectionId', filters.connectionId);
  if (filters.outcome) params.set('outcome', filters.outcome);
  params.set('limit', String(filters.limit));
  const res = await fetch(`/api/ssh/admin/audit?${params.toString()}`, { credentials: 'include' });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const data = (await res.json()) as { audit: SshAuditRow[] };
  return data.audit ?? [];
}

const ACTION_HINTS = [
  'ssh.exec',
  'ssh.upload',
  'ssh.download',
  'ssh.connection.upsert',
  'ssh.connection.disable',
  'ssh.connection.enable',
  'ssh.connection.delete',
  'ssh.connection.host_key.tofu_record',
  'ssh.connection.host_key.verify',
  'ssh.connection.host_key.mismatch',
  'ssh.connection.host_key.replace',
  'ssh.grant.create',
  'ssh.grant.delete',
  'ssh.grant.use',
  'ssh.abuse.lock',
  'ssh.abuse.unlock_manual',
  'ssh.master_key.rotate.start',
];

export function SshAuditLog() {
  const { t } = useTranslation('settings');
  const [filters, setFilters] = useState<Filters>({
    action: '',
    ownerId: '',
    connectionId: '',
    outcome: '',
    limit: 100,
  });
  const { data, isLoading, error, refetch, isFetching } = useQuery({
    queryKey: ['ssh', 'admin', 'audit', filters],
    queryFn: () => fetchAudit(filters),
    staleTime: 5_000,
  });

  function update<K extends keyof Filters>(key: K, value: Filters[K]) {
    setFilters(prev => ({ ...prev, [key]: value }));
  }

  return (
    <div className="space-y-3">
      <h3 className="text-sm font-semibold text-slate-900">{t('ssh.audit.title')}</h3>

      <div className="grid grid-cols-2 md:grid-cols-4 gap-2 text-2xs">
        <label className="block">
          <div className="font-semibold text-slate-500 uppercase tracking-wide mb-0.5">Action</div>
          <input
            type="text"
            value={filters.action}
            onChange={e => update('action', e.target.value)}
            list="ssh-audit-actions"
            placeholder="ssh.exec"
            className="w-full text-2xs px-2 py-1 border border-hairline rounded font-mono"
          />
          <datalist id="ssh-audit-actions">
            {ACTION_HINTS.map(a => <option key={a} value={a} />)}
          </datalist>
        </label>
        <label className="block">
          <div className="font-semibold text-slate-500 uppercase tracking-wide mb-0.5">Owner ID</div>
          <input
            type="text"
            value={filters.ownerId}
            onChange={e => update('ownerId', e.target.value)}
            placeholder="user id"
            className="w-full text-2xs px-2 py-1 border border-hairline rounded font-mono"
          />
        </label>
        <label className="block">
          <div className="font-semibold text-slate-500 uppercase tracking-wide mb-0.5">Connection ID</div>
          <input
            type="text"
            value={filters.connectionId}
            onChange={e => update('connectionId', e.target.value)}
            placeholder="conn id"
            className="w-full text-2xs px-2 py-1 border border-hairline rounded font-mono"
          />
        </label>
        <label className="block">
          <div className="font-semibold text-slate-500 uppercase tracking-wide mb-0.5">Outcome</div>
          <select
            value={filters.outcome}
            onChange={e => update('outcome', e.target.value)}
            className="w-full text-2xs px-2 py-1 border border-hairline rounded"
          >
            <option value="">(any)</option>
            <option value="pending">pending</option>
            <option value="success">success</option>
            <option value="failed">failed</option>
            <option value="denied">denied</option>
            <option value="aborted">aborted</option>
          </select>
        </label>
      </div>

      <div className="flex items-center gap-2">
        <button
          onClick={() => refetch()}
          disabled={isFetching}
          className="px-2 h-6 text-2xs text-slate-700 border border-hairline rounded hover:bg-surface disabled:opacity-50"
        >
          {isFetching ? t('ssh.audit.refreshing') : t('ssh.audit.reload')}
        </button>
        <span className="text-2xs text-slate-500">{t('ssh.audit.countDisplay', { count: data?.length ?? 0, limit: filters.limit })}</span>
      </div>

      {isLoading && <div className="text-xs text-slate-400">Loading…</div>}
      {error && <div className="text-xs text-red-500">{String(error)}</div>}

      <div className="overflow-x-auto rounded border border-hairline">
        <table className="w-full text-2xs">
          <thead className="bg-surface/60 border-b border-hairline">
            <tr className="text-left">
              <th className="px-2 py-1 font-semibold text-slate-700">Time</th>
              <th className="px-2 py-1 font-semibold text-slate-700">Action</th>
              <th className="px-2 py-1 font-semibold text-slate-700">Outcome</th>
              <th className="px-2 py-1 font-semibold text-slate-700">Actor</th>
              <th className="px-2 py-1 font-semibold text-slate-700">Connection</th>
              <th className="px-2 py-1 font-semibold text-slate-700">Detail</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-hairline bg-canvas">
            {(data ?? []).map(r => (
              <tr key={r.id} className="hover:bg-surface/40">
                <td className="px-2 py-1 font-mono text-slate-600 whitespace-nowrap">{r.startedAt}</td>
                <td className="px-2 py-1 font-mono text-slate-800 whitespace-nowrap">{r.action}</td>
                <td className="px-2 py-1">
                  <OutcomeBadge outcome={r.outcome} />
                </td>
                <td className="px-2 py-1 font-mono text-slate-600 truncate max-w-[100px]">{r.actingUserId ?? '-'}</td>
                <td className="px-2 py-1 font-mono text-slate-600 truncate max-w-[100px]">{r.connectionId ?? '-'}</td>
                <td className="px-2 py-1 font-mono text-slate-700 truncate max-w-[280px]" title={r.detail ? JSON.stringify(r.detail) : ''}>
                  {r.reason ? <span className="text-slate-500">{r.reason}</span> : null}
                  {r.detail !== null && r.detail !== undefined ? (
                    <span className="ml-1">{JSON.stringify(r.detail)}</span>
                  ) : null}
                </td>
              </tr>
            ))}
            {(data ?? []).length === 0 && !isLoading && (
              <tr><td colSpan={6} className="px-2 py-4 text-center text-slate-400">{t('ssh.audit.empty')}</td></tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function OutcomeBadge({ outcome }: { outcome: string }) {
  const colorMap: Record<string, string> = {
    pending: 'bg-slate-100 text-slate-600',
    success: 'bg-emerald-50 dark:bg-emerald-500/15 text-emerald-700 dark:text-emerald-300',
    failed: 'bg-red-50 dark:bg-red-500/15 text-red-700 dark:text-red-300',
    denied: 'bg-amber-50 dark:bg-amber-500/15 text-amber-700 dark:text-amber-300',
    aborted: 'bg-slate-100 text-slate-500',
  };
  const cls = colorMap[outcome] ?? 'bg-slate-100 text-slate-600';
  return (
    <span className={`inline-block px-1.5 py-0.5 rounded text-[10px] font-medium leading-none ${cls}`}>
      {outcome}
    </span>
  );
}
