import { useEffect, useState } from 'react';
import { Badge, Button, Card, ErrorState, Skeleton, Table, type BadgeProps } from '@platform-modules/ui-primitives';
import { ScreenHeader } from './ScreenHeader.js';

type HealthStatus = 'ok' | 'degraded' | 'down';
type HealthResult = { name: string; status: HealthStatus; detail?: string; latencyMs?: number };
type SiteHealth = { status: HealthStatus; checks: HealthResult[] };

type LoadStatus = 'loading' | 'idle' | 'error';

// Status → Badge tone. The status word is ALSO rendered as the Badge's text (STATUS_LABEL), so
// colour is never the sole status signal (a11y: status must not be conveyed by colour alone).
function statusTone(status: HealthStatus): NonNullable<BadgeProps['tone']> {
  if (status === 'ok') return 'success';
  if (status === 'degraded') return 'warning';
  return 'danger';
}

const STATUS_LABEL: Record<HealthStatus, string> = {
  ok: 'Operational',
  degraded: 'Degraded',
  down: 'Down',
};

const OVERALL_SUMMARY: Record<HealthStatus, string> = {
  ok: 'All systems operational.',
  degraded: 'Some systems are degraded.',
  down: 'One or more systems are down.',
};

export default function HealthScreen() {
  const [health, setHealth] = useState<SiteHealth | null>(null);
  const [status, setStatus] = useState<LoadStatus>('loading');
  const [errorMessage, setErrorMessage] = useState('');
  const [reloadKey, setReloadKey] = useState(0);

  useEffect(() => {
    let active = true;
    void (async () => {
      setStatus('loading');
      setErrorMessage('');
      try {
        const res = await fetch('/api/admin/health', { credentials: 'same-origin' });
        const body: unknown = await res.json().catch(() => null);
        if (!res.ok) {
          const message = (body as { error?: { message?: string } } | null)?.error?.message ?? res.statusText;
          throw new Error(message);
        }
        if (!active) return;
        setHealth(body as SiteHealth);
        setStatus('idle');
      } catch (error: unknown) {
        if (!active) return;
        setHealth(null);
        setErrorMessage(error instanceof Error ? error.message : String(error));
        setStatus('error');
      }
    })();
    return () => {
      active = false;
    };
  }, [reloadKey]);

  return (
    <section aria-labelledby="health-heading">
      {/* Exactly one primary action per screen — the Re-check button. In the error state the
          ErrorState below carries the (same) Try-again action, so this is hidden then. */}
      <ScreenHeader
        headingId="health-heading"
        title="Site health"
        description="Reachability of the services this site depends on."
        actions={
          status !== 'error' ? (
            <Button
              tone="accent"
              radius="sm"
              size="sm"
              type="button"
              disabled={status === 'loading'}
              onClick={() => setReloadKey((k) => k + 1)}
            >
              Re-check
            </Button>
          ) : null
        }
      />

      {status === 'loading' ? (
        <div className="flex flex-col gap-4" aria-hidden="true">
          <Skeleton variant="block" />
        </div>
      ) : null}

      {status === 'error' ? (
        <ErrorState
          variant="inline"
          title="Health status couldn't load"
          message={errorMessage}
          action={
            <Button tone="accent" radius="sm" size="sm" type="button" onClick={() => setReloadKey((k) => k + 1)}>
              Try again
            </Button>
          }
        />
      ) : null}

      {status === 'idle' && health ? (
        <div className="flex flex-col gap-6">
          <Card
            header={
              <div className="flex items-center justify-between gap-4">
                <h2 className="admin-display text-lg text-fg">Overall status</h2>
                <Badge tone={statusTone(health.status)}>{STATUS_LABEL[health.status]}</Badge>
              </div>
            }
          >
            <p className="text-sm text-fg-muted">{OVERALL_SUMMARY[health.status]}</p>
          </Card>

          <Table caption="Per-service health checks">
            <Table.Head>
              <Table.Row>
                <Table.Th scope="col">Service</Table.Th>
                <Table.Th scope="col">Status</Table.Th>
                <Table.Th scope="col">Latency</Table.Th>
                <Table.Th scope="col">Detail</Table.Th>
              </Table.Row>
            </Table.Head>
            <Table.Body>
              {health.checks.map((check) => (
                <Table.Row key={check.name}>
                  <Table.Td>{check.name}</Table.Td>
                  <Table.Td>
                    <Badge tone={statusTone(check.status)}>{STATUS_LABEL[check.status]}</Badge>
                  </Table.Td>
                  <Table.Td>{check.latencyMs == null ? '—' : `${check.latencyMs} ms`}</Table.Td>
                  <Table.Td>{check.detail ?? '—'}</Table.Td>
                </Table.Row>
              ))}
            </Table.Body>
          </Table>
        </div>
      ) : null}
    </section>
  );
}
