import { useState } from 'react'
import { Badge, DataTable, EmptyState, ErrorState, PageHeader, Skeleton, Toolbar } from '@sims/ui'
import { getAudit, getEmployees, type AuditPage, type Employee } from '../api'
import { useData } from './Clients'

const PAGE_SIZE = 50

/** Compact before→after diff of the changed keys in an audit row. */
function diff(before: string | null, after: string | null): string {
  const b = before !== null ? JSON.parse(before) as Record<string, unknown> : {}
  const a = after !== null ? JSON.parse(after) as Record<string, unknown> : {}
  const keys = [...new Set([...Object.keys(b), ...Object.keys(a)])]
  const changed = keys.filter((k) => JSON.stringify(b[k]) !== JSON.stringify(a[k]))
  if (changed.length === 0) return before === null && after !== null ? 'created' : after === null ? '' : '—'
  return changed.slice(0, 6).map((k) => `${k}: ${JSON.stringify(a[k] ?? b[k])}`).join(', ')
}

/** Audit log viewer (D27, owner-only): who did what, filterable + paginated. */
export function Audit() {
  const [entity, setEntity] = useState('')
  const [action, setAction] = useState('')
  const [page, setPage] = useState(1)
  const list = useData<AuditPage | undefined>(
    () => getAudit({ entity, action, page, pageSize: PAGE_SIZE }), [entity, action, page])
  const emps = useData<{ employees: Employee[]; total: number } | undefined>(() => getEmployees(), [])
  const nameOf = (id: string) => id === 'system' ? 'system'
    : (emps.data?.employees.find((e) => e.id === id)?.displayName ?? id.slice(0, 8))

  const data = list.data
  const totalPages = data !== undefined ? Math.max(1, Math.ceil(data.total / data.pageSize)) : 1

  return (
    <div className="wf-page">
      <PageHeader title="Audit log" desc="Every change, append-only — who did what, when. Owner-only." />
      <Toolbar>
        <select className="wf" style={{ maxWidth: 200 }} value={entity} aria-label="Entity"
          onChange={(e) => { setEntity(e.target.value); setPage(1) }}>
          <option value="">Entity: any</option>
          {(data?.facets.entities ?? []).map((x) => <option key={x} value={x}>{x}</option>)}
        </select>
        <select className="wf" style={{ maxWidth: 200 }} value={action} aria-label="Action"
          onChange={(e) => { setAction(e.target.value); setPage(1) }}>
          <option value="">Action: any</option>
          {(data?.facets.actions ?? []).map((x) => <option key={x} value={x}>{x}</option>)}
        </select>
        <span style={{ flex: 1 }} />
        {data !== undefined && <Badge>{data.total} entries</Badge>}
      </Toolbar>
      {list.error !== undefined ? <ErrorState message={list.error} onRetry={list.reload} />
        : data === undefined ? <Skeleton rows={8} />
        : data.rows.length === 0 ? <EmptyState>No audit entries match.</EmptyState> : (
        <>
          <DataTable
            columns={[
              { key: 'when', label: 'When' }, { key: 'who', label: 'Who' },
              { key: 'action', label: 'Action' }, { key: 'entity', label: 'Entity' },
              { key: 'change', label: 'Change' },
            ]}
            rows={data.rows.map((r) => ({
              when: r.at_wall.replace('T', ' ').slice(0, 19),
              who: nameOf(r.user_id),
              action: <Badge>{r.action}</Badge>,
              entity: <span className="mono" style={{ fontSize: 12 }}>{r.entity}</span>,
              change: <span style={{ fontSize: 12.5, opacity: 0.85 }}>{diff(r.before_json, r.after_json)}</span>,
            }))}
          />
          <Toolbar>
            <span style={{ flex: 1 }} />
            <button type="button" className="wf" disabled={data.page <= 1} onClick={() => setPage((p) => Math.max(1, p - 1))}>‹ Prev</button>
            <span style={{ fontSize: 12, opacity: 0.7 }}>Page {data.page} / {totalPages}</span>
            <button type="button" className="wf" disabled={data.page >= totalPages} onClick={() => setPage((p) => p + 1)}>Next ›</button>
          </Toolbar>
        </>
      )}
    </div>
  )
}
