'use client'

import { useState } from 'react'

import { Button, Notice, Segmented } from '@/components/ui/controls'
import {
  Badge,
  EmptyState,
  KeyValue,
  Meter,
  Panel,
  PanelBody,
  PanelHeader,
  StatCard,
  StateBadge,
} from '@/components/ui/display'
import type { GridState } from '@/lib/domain/enums'
import { useI18n } from '@/components/providers/i18n-provider'
import { api } from '@/lib/api/client'
import { cn } from '@/lib/cn'
import { formatDateTime, formatNumber } from '@/lib/i18n/translate'

/**
 * The Integration Hub (4.1).
 *
 * One rule shapes every label on this screen: **a demonstration source is never described
 * as connected without the word demo attached.** The server derives that label from mode
 * and status together and sends it down as a single string; nothing here reconstructs it
 * from the parts, because a screen that reassembled the label would be a screen that could
 * forget half of it.
 *
 * The second rule is that every number moves. Sync, test, mapping and fault injection all
 * call the real endpoints and re-read what comes back — including when what comes back is
 * worse. Injecting a fault and watching quality fall is the demonstration; a fault that
 * changed nothing but a badge would demonstrate the badge.
 */

export interface ConnectorView {
  code: string
  name: string
  nameAr: string
  kind: string
  protocol: string
  mode: 'live' | 'demo'
  status: string
  label: string
  direction: string
  description: string
  descriptionAr: string
  endpoint: string
  authKind: string
  secretRef: string
  pollSeconds: number
  timeoutMs: number
  lastConnectedAt: number | null
  lastSyncAt: number | null
  latencyMs: number
  recordsReceived: number
  errorCount: number
  healthScore: number
  dataQuality: number
  eventsPerMin: number
  faultKind: string
  mappingCount: number
  isActive: boolean
}

export interface HubOverviewView {
  total: number
  connected: number
  disconnected: number
  degraded: number
  error: number
  demo: number
  live: number
  lastSyncAt: number | null
  throughputPerMin: number
  meanQuality: number
  meanHealth: number
  connectors: ConnectorView[]
}

interface MappingView {
  sourceField: string
  targetField: string
  dataType: string
  sourceUnit: string
  targetUnit: string
  transform: string
  minValue: number | null
  maxValue: number | null
  isRequired: boolean
  notes: string
}

interface EventView {
  kind: string
  recordsIn: number
  recordsAccepted: number
  recordsRejected: number
  latencyMs: number
  detail: string
  detailAr: string
  severity: string
  ts: number
}

interface SampleView {
  ts: number
  healthScore: number
  dataQuality: number
  latencyMs: number
  completeness: number
  freshness: number
  validity: number
  consistency: number
  availability: number
  trust: number
}

interface ConnectorDetailView extends ConnectorView {
  mappings: MappingView[]
  events: EventView[]
  samples: SampleView[]
}

interface SyncResultView {
  code: string
  label: string
  recordsIn: number
  accepted: number
  rejected: number
  latencyMs: number
  quality: {
    score: number
    band: string
    completeness: number
    freshness: number
    validity: number
    consistency: number
    availability: number
    trust: number
    weakest: { key: string; value: number }
  }
  health: number
  rejectionReasons: Array<{ reason: string; count: number; detail: string; detailAr: string }>
  pipeline: Array<{ stage: string; recordsIn: number; recordsOut: number; dropped: number; note: string; noteAr: string }>
  preview: Array<{
    assetCode: string
    ts: number
    fields: Array<{ field: string; value: unknown; unit: string; sourceValue: unknown; sourceUnit: string }>
  }>
  faultKind: string
}

// The engine's own vocabulary, not a parallel one: a screen with its own fault names
// would be a screen that could offer a fault the injector does not implement.
const FAULTS = ['connection_loss', 'high_latency', 'stale_data', 'sensor_failure', 'bad_data', 'partial_data'] as const

/** The readiness payload (§9). Mirrors the route's shape; nothing is derived here. */
interface ReadinessCheckView {
  key: string
  ok: boolean
  required: boolean
  message: string
  messageAr: string
}

interface ReadinessReportView {
  protocol: string
  adapter: {
    label: string
    labelAr: string
    typicalSource: string
    reads: string[]
    writeSupported: boolean
    refuses: string[]
    transport: string
    expectedLatencySec: number
  } | null
  state: string
  completionPct: number
  checks: ReadinessCheckView[]
  blocking: ReadinessCheckView[]
  nextStep: string | null
  nextStepAr: string | null
  canClaimLive: boolean
  note: string
  noteAr: string
}

interface ReadinessOverviewView {
  liveReady: number
  demoVerified: number
  incomplete: number
  refuses: string[]
  rows: Array<{ code: string; name: string; nameAr: string; kind: string; mode: string; report: ReadinessReportView }>
  note: string
  noteAr: string
}

const TABS = ['overview', 'mapping', 'flow', 'health', 'readiness', 'events', 'fault'] as const
type TabKey = (typeof TABS)[number]

/**
 * Connection state as a grid state, so the hub uses the platform's one severity palette
 * rather than inventing a second one. A source that has stopped delivering is a watch, not
 * a neutral chip.
 */
function statusState(status: string): GridState {
  if (status === 'connected') return 'normal'
  if (status === 'degraded' || status === 'connecting') return 'warning'
  if (status === 'error') return 'critical'
  return 'watch'
}

function scoreTone(value: number): string {
  if (value >= 85) return 'text-normal'
  if (value >= 65) return 'text-watch'
  if (value >= 45) return 'text-warning'
  return 'text-critical'
}

export function IntegrationHub({
  initialOverview,
  canSync,
  canMap,
  canSimulate,
}: {
  initialOverview: HubOverviewView
  canSync: boolean
  canMap: boolean
  canSimulate: boolean
}) {
  const { t, locale } = useI18n()
  const [overview, setOverview] = useState(initialOverview)
  const [selected, setSelected] = useState<string | null>(null)
  const [detail, setDetail] = useState<ConnectorDetailView | null>(null)
  const [tab, setTab] = useState<TabKey>('overview')
  const [sync, setSync] = useState<SyncResultView | null>(null)
  const [readiness, setReadiness] = useState<ReadinessOverviewView | null>(null)
  const [busy, setBusy] = useState<string | null>(null)
  const [notice, setNotice] = useState<{ tone: 'info' | 'warning' | 'danger'; text: string } | null>(null)

  const num = (value: number, digits = 0) =>
    formatNumber(locale, value, { maximumFractionDigits: digits })

  const openConnector = async (code: string) => {
    setSelected(code)
    setTab('overview')
    setSync(null)
    setNotice(null)
    setBusy('open')
    try {
      setDetail(await api.get<ConnectorDetailView>(`/api/integrations/${code}`))
    } catch (caught) {
      setNotice({ tone: 'danger', text: message(caught, t) })
    } finally {
      setBusy(null)
    }
  }

  /** Loaded when the readiness tab is first opened: it reads every connector, not one. */
  const loadReadiness = async () => {
    setBusy('readiness')
    try {
      setReadiness(await api.get<ReadinessOverviewView>('/api/integrations/readiness'))
    } catch (caught) {
      setNotice({ tone: 'danger', text: message(caught, t) })
    } finally {
      setBusy(null)
    }
  }

  const refresh = async (code: string) => {
    const [hub, next] = await Promise.all([
      api.get<HubOverviewView>('/api/integrations'),
      api.get<ConnectorDetailView>(`/api/integrations/${code}`),
    ])
    setOverview(hub)
    setDetail(next)
  }

  const act = async (label: string, run: () => Promise<void>) => {
    setBusy(label)
    setNotice(null)
    try {
      await run()
    } catch (caught) {
      setNotice({ tone: 'danger', text: message(caught, t) })
    } finally {
      setBusy(null)
    }
  }

  const runSync = (code: string) =>
    act('sync', async () => {
      const result = await api.post<SyncResultView>(`/api/integrations/${code}/sync`, { batchSize: 60 })
      setSync(result)
      setTab('flow')
      await refresh(code)
    })

  const runPreview = (code: string) =>
    act('preview', async () => {
      setSync(await api.get<SyncResultView>(`/api/integrations/${code}/data-preview`))
      setTab('flow')
    })

  const runTest = (code: string) =>
    act('test', async () => {
      const result = await api.post<{ reachable: boolean; detail: string; detailAr: string; mode: string }>(
        `/api/integrations/${code}/test`,
        {},
      )
      setNotice({
        tone: result.reachable ? 'info' : 'warning',
        text: locale === 'ar' ? result.detailAr : result.detail,
      })
      await refresh(code)
    })

  const setFault = (code: string, faultKind: string) =>
    act('fault', async () => {
      await api.post(`/api/integrations/${code}/fault`, { faultKind })
      setNotice({
        tone: 'warning',
        text: faultKind ? t('integrations.hub.faultInjected') : t('integrations.hub.faultCleared'),
      })
      await refresh(code)
    })

  const removeMapping = (code: string, sourceField: string) =>
    act('mapping', async () => {
      await api.delete(`/api/integrations/${code}/mapping?sourceField=${encodeURIComponent(sourceField)}`)
      setNotice({ tone: 'warning', text: t('integrations.hub.mappingRemoved') })
      await refresh(code)
    })

  const saveMapping = (code: string, mapping: MappingView) =>
    act('mapping', async () => {
      await api.post(`/api/integrations/${code}/mapping`, {
        sourceField: mapping.sourceField,
        targetField: mapping.targetField,
        dataType: mapping.dataType,
        sourceUnit: mapping.sourceUnit,
        targetUnit: mapping.targetUnit,
        minValue: mapping.minValue,
        maxValue: mapping.maxValue,
        isRequired: mapping.isRequired,
      })
      setNotice({ tone: 'info', text: t('integrations.hub.mappingSaved') })
      await refresh(code)
    })

  return (
    <div className="space-y-4" data-testid="integration-hub">
      <Notice tone="info">{t('integrations.hub.honesty')}</Notice>

      <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
        <StatCard
          label={t('integrations.hub.sources')}
          value={num(overview.total)}
          hint={`${num(overview.demo)} ${t('integrations.hub.modeDemo')}`}
        />
        <StatCard
          label={t('integrations.hub.throughput')}
          value={num(overview.throughputPerMin, 1)}
          state="normal"
        />
        <StatCard
          label={t('integrations.hub.meanQuality')}
          value={`${num(overview.meanQuality, 1)}%`}
          state={overview.meanQuality >= 85 ? 'normal' : overview.meanQuality >= 65 ? 'watch' : 'warning'}
        />
        <StatCard
          label={t('integrations.hub.meanHealth')}
          value={`${num(overview.meanHealth, 1)}%`}
          state={overview.meanHealth >= 85 ? 'normal' : overview.meanHealth >= 65 ? 'watch' : 'warning'}
        />
      </div>

      {notice ? <Notice tone={notice.tone}>{notice.text}</Notice> : null}

      {overview.connectors.length === 0 ? (
        <EmptyState title={t('uiState.empty')} body={t('integrations.hub.empty')} />
      ) : (
        <div className="grid gap-3 lg:grid-cols-2 xl:grid-cols-3">
          {overview.connectors.map((connector) => (
            <button
              key={connector.code}
              type="button"
              onClick={() => openConnector(connector.code)}
              data-connector={connector.code}
              data-connector-label={connector.label}
              className={cn(
                'rounded-[--radius-panel] border p-4 text-start transition-colors',
                selected === connector.code
                  ? 'border-brand/50 bg-brand/8'
                  : 'border-border bg-surface-2/40 hover:border-brand/30',
              )}
            >
              <div className="flex items-start justify-between gap-2">
                <div className="min-w-0">
                  <p className="truncate text-sm font-medium text-text">
                    {locale === 'ar' ? connector.nameAr : connector.name}
                  </p>
                  <p className="mt-0.5 font-mono text-[10px] uppercase text-text-faint">
                    {connector.kind} · {connector.protocol}
                  </p>
                </div>
                <StateBadge
                  state={statusState(connector.status)}
                  label={connectorLabelText(connector, t)}
                  size="sm"
                />
              </div>

              <div className="mt-3 grid grid-cols-3 gap-2 text-[11px]">
                <div>
                  <p className="text-text-faint">{t('integrations.hub.quality')}</p>
                  <p className={cn('font-mono tabular-nums', scoreTone(connector.dataQuality))}>
                    {num(connector.dataQuality, 1)}%
                  </p>
                </div>
                <div>
                  <p className="text-text-faint">{t('integrations.hub.health')}</p>
                  <p className={cn('font-mono tabular-nums', scoreTone(connector.healthScore))}>
                    {num(connector.healthScore, 1)}%
                  </p>
                </div>
                <div>
                  <p className="text-text-faint">{t('integrations.hub.latency')}</p>
                  <p className="font-mono tabular-nums text-text-muted">{num(connector.latencyMs)} ms</p>
                </div>
              </div>

              {connector.faultKind ? (
                <p className="mt-2 text-[11px] text-warning">
                  {t('integrations.hub.faultActive')}: {t(`integrations.fault.${connector.faultKind}`)}
                </p>
              ) : null}
            </button>
          ))}
        </div>
      )}

      {detail ? (
        <Panel>
          <PanelHeader
            title={locale === 'ar' ? detail.nameAr : detail.name}
            subtitle={locale === 'ar' ? detail.descriptionAr : detail.description}
            action={
              <div className="flex flex-wrap gap-1.5">
                {canSync ? (
                  <>
                    <Button size="sm" variant="secondary" onClick={() => runTest(detail.code)} disabled={busy !== null}>
                      {busy === 'test' ? t('integrations.hub.testing') : t('integrations.hub.test')}
                    </Button>
                    <Button size="sm" variant="primary" onClick={() => runSync(detail.code)} disabled={busy !== null}>
                      {busy === 'sync' ? t('integrations.hub.syncing') : t('integrations.hub.sync')}
                    </Button>
                  </>
                ) : null}
                <Button size="sm" variant="ghost" onClick={() => runPreview(detail.code)} disabled={busy !== null}>
                  {t('integrations.hub.preview')}
                </Button>
              </div>
            }
          />
          <PanelBody className="space-y-4">
            <Segmented
              value={tab}
              onChange={(next) => {
                setTab(next)
                if (next === 'readiness' && !readiness) void loadReadiness()
              }}
              ariaLabel={t('integrations.hub.title')}
              options={TABS.map((key) => ({
                value: key,
                label: t(`integrations.hub.tab${key[0].toUpperCase()}${key.slice(1)}`),
              }))}
            />

            {tab === 'overview' ? <Overview detail={detail} /> : null}
            {tab === 'mapping' ? (
              <MappingStudio
                detail={detail}
                canMap={canMap}
                busy={busy !== null}
                onSave={(mapping) => saveMapping(detail.code, mapping)}
                onRemove={(sourceField) => removeMapping(detail.code, sourceField)}
              />
            ) : null}
            {tab === 'flow' ? <Flow sync={sync} /> : null}
            {tab === 'health' ? <Health detail={detail} sync={sync} /> : null}
            {tab === 'readiness' ? <Readiness code={detail.code} /> : null}
            {tab === 'events' ? <Events detail={detail} /> : null}
            {tab === 'fault' ? (
              <FaultPanel
                detail={detail}
                canSimulate={canSimulate}
                busy={busy !== null}
                onSet={(kind) => setFault(detail.code, kind)}
              />
            ) : null}
          </PanelBody>
        </Panel>
      ) : null}
    </div>
  )

  // ── Tabs ──────────────────────────────────────────────────────────────────

  /**
   * Live readiness (§9–§10).
   *
   * A checklist rather than a verdict: what this source would need before its readings
   * could carry a decision, evaluated against the configuration as it stands. The
   * read-only row is always present and always satisfied — the guarantee is stated, not
   * inferred from the absence of a control button.
   */
  function Readiness({ code }: { code: string }) {
    const row = readiness?.rows.find((entry) => entry.code === code) ?? null
    if (!readiness || !row) {
      return <EmptyState title={t('integrations.hub.tabReadiness')} body={t('common.loading')} />
    }

    const report = row.report
    return (
      <div className="space-y-3" data-testid="connector-readiness" data-state={report.state}>
        <div className="flex flex-wrap items-center gap-2">
          <StateBadge
            state={report.canClaimLive ? 'normal' : report.blocking.length > 0 ? 'warning' : 'watch'}
            label={t(`readiness.state.${report.state}`)}
          />
          <Badge tone="muted">{report.completionPct}%</Badge>
          {report.adapter ? <Badge tone="info">{report.adapter.label}</Badge> : null}
          <span data-testid="read-only">
            <Badge tone="accent">{t('readiness.readOnly')}</Badge>
          </span>
        </div>

        <p className="text-[11px] leading-relaxed text-muted">
          {locale === 'ar' ? report.noteAr : report.note}
        </p>

        {report.nextStep ? (
          <Notice tone="warning">
            {t('readiness.nextStep')}: {locale === 'ar' ? report.nextStepAr : report.nextStep}
          </Notice>
        ) : null}

        <ul className="space-y-1.5" data-testid="readiness-checks">
          {report.checks.map((check) => (
            <li
              key={check.key}
              data-check={check.key}
              data-ok={check.ok}
              className={cn(
                'flex items-start gap-2 rounded-[--radius-panel] border p-2.5 text-[11px]',
                check.ok ? 'border-border bg-surface-2' : 'border-warning/40 bg-warning/8',
              )}
            >
              <span className={cn('font-mono text-[10px] uppercase', check.ok ? 'text-normal' : 'text-warning')}>
                {check.ok ? 'OK' : check.required ? 'BLOCK' : 'WARN'}
              </span>
              <span className="min-w-0">
                <span className="block font-medium text-fg">{t(`readiness.check.${check.key}`)}</span>
                <span className="block text-muted">{locale === 'ar' ? check.messageAr : check.message}</span>
              </span>
            </li>
          ))}
        </ul>

        {report.adapter ? (
          <div className="rounded-[--radius-panel] border border-border bg-surface-2 p-3 text-[11px]">
            <div className="font-medium text-fg">{t('readiness.adapter')}</div>
            <dl className="grid gap-x-6 gap-y-1 pt-1 sm:grid-cols-2">
              <KeyValue label={t('readiness.transport')} value={report.adapter.transport} />
              <KeyValue label={t('readiness.expectedLatency')} value={`${report.adapter.expectedLatencySec} s`} />
              <KeyValue label={t('readiness.reads')} value={report.adapter.reads.join(', ')} />
              <KeyValue label={t('readiness.writes')} value={t('readiness.noWrite')} />
            </dl>
            <p className="pt-2 text-muted">
              {t('readiness.refuses')}:{' '}
              <span className="font-mono text-fg">{report.adapter.refuses.join(' · ')}</span>
            </p>
          </div>
        ) : null}
      </div>
    )
  }

  function Overview({ detail: connector }: { detail: ConnectorDetailView }) {
    return (
      <div className="space-y-3">
        <dl className="grid gap-x-6 gap-y-1 sm:grid-cols-2">
          <KeyValue label={t('integrations.hub.kind')} value={connector.kind} />
          <KeyValue label={t('integrations.hub.protocol')} value={connector.protocol} />
          <KeyValue label={t('integrations.direction.' + connector.direction)} value={connector.label} mono />
          <KeyValue label={t('integrations.hub.endpoint')} value={connector.endpoint || '—'} mono />
          <KeyValue label={t('integrations.hub.auth')} value={connector.authKind} />
          <KeyValue
            label={t('integrations.hub.secretRef')}
            value={connector.secretRef || t('integrations.hub.noSecret')}
            mono
          />
          <KeyValue label={t('integrations.hub.poll')} value={`${num(connector.pollSeconds)} s`} />
          <KeyValue label={t('integrations.hub.timeout')} value={`${num(connector.timeoutMs)} ms`} />
          <KeyValue label={t('integrations.hub.records')} value={num(connector.recordsReceived)} />
          <KeyValue label={t('integrations.hub.errors')} value={num(connector.errorCount)} />
          <KeyValue
            label={t('integrations.hub.lastSync')}
            value={
              connector.lastSyncAt
                ? formatDateTime(locale, connector.lastSyncAt)
                : t('integrations.hub.never')
            }
          />
          <KeyValue label={t('integrations.hub.mappings')} value={num(connector.mappings.length)} />
        </dl>
        <p className="text-[11px] leading-relaxed text-text-faint">{t('integrations.hub.secretNote')}</p>
      </div>
    )
  }

  function MappingStudio({
    detail: connector,
    canMap: allowed,
    busy: working,
    onSave,
    onRemove,
  }: {
    detail: ConnectorDetailView
    canMap: boolean
    busy: boolean
    onSave: (mapping: MappingView) => void
    onRemove: (sourceField: string) => void
  }) {
    if (connector.mappings.length === 0) {
      return <Notice tone="warning">{t('integrations.hub.noMappings')}</Notice>
    }

    return (
      <div className="space-y-2">
        <div className="overflow-x-auto">
          <table className="w-full min-w-[720px] text-[12px]">
            <thead className="text-[10px] uppercase tracking-wide text-text-faint">
              <tr className="border-b border-border">
                <th className="py-2 text-start font-medium">{t('integrations.hub.sourceField')}</th>
                <th className="py-2 text-start font-medium">{t('integrations.hub.targetField')}</th>
                <th className="py-2 text-start font-medium">{t('integrations.hub.sourceUnit')}</th>
                <th className="py-2 text-start font-medium">{t('integrations.hub.targetUnit')}</th>
                <th className="py-2 text-start font-medium">{t('integrations.hub.range')}</th>
                <th className="py-2 text-end font-medium" />
              </tr>
            </thead>
            <tbody>
              {connector.mappings.map((mapping) => (
                <tr key={mapping.sourceField} className="border-b border-border/50" data-mapping={mapping.sourceField}>
                  <td className="py-2 font-mono text-[11px]">{mapping.sourceField}</td>
                  <td className="py-2 font-mono text-[11px] text-brand">{mapping.targetField}</td>
                  <td className="py-2 text-text-muted">{mapping.sourceUnit || '—'}</td>
                  <td className="py-2 text-text-muted">{mapping.targetUnit || '—'}</td>
                  <td className="py-2 tabular-nums text-text-muted">
                    {mapping.minValue === null && mapping.maxValue === null
                      ? t('integrations.hub.unbounded')
                      : `${mapping.minValue ?? '−∞'} … ${mapping.maxValue ?? '∞'}`}
                  </td>
                  <td className="py-2 text-end">
                    <span className="me-2 text-[10px] uppercase tracking-wide text-text-faint">
                      {mapping.isRequired ? t('integrations.hub.required') : t('integrations.hub.optional')}
                    </span>
                    {allowed ? (
                      <>
                        <Button
                          size="sm"
                          variant="ghost"
                          disabled={working}
                          onClick={() => onSave({ ...mapping, isRequired: !mapping.isRequired })}
                        >
                          {t('integrations.hub.saveMapping')}
                        </Button>
                        <Button size="sm" variant="ghost" disabled={working} onClick={() => onRemove(mapping.sourceField)}>
                          {t('integrations.hub.removeMapping')}
                        </Button>
                      </>
                    ) : null}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    )
  }

  function Flow({ sync: result }: { sync: SyncResultView | null }) {
    if (!result) {
      return <EmptyState title={t('uiState.empty')} body={t('integrations.hub.previewNote')} />
    }

    return (
      <div className="space-y-4" data-testid="integration-flow">
        {/* The pipeline, stage by stage, with what each one dropped. */}
        <ol className="grid gap-2 sm:grid-cols-3 xl:grid-cols-6">
          {result.pipeline.map((step) => (
            <li key={step.stage} className="rounded-lg border border-border bg-surface-2/40 p-2.5">
              <p className="text-[10px] uppercase tracking-wide text-text-faint">
                {t(`integrations.hub.stage${step.stage[0].toUpperCase()}${step.stage.slice(1)}`)}
              </p>
              <p className="mt-1 font-mono text-sm tabular-nums text-text">{num(step.recordsOut)}</p>
              <p className={cn('text-[10px] tabular-nums', step.dropped > 0 ? 'text-warning' : 'text-text-faint')}>
                −{num(step.dropped)} {t('integrations.hub.stageDropped')}
              </p>
            </li>
          ))}
        </ol>

        {result.rejectionReasons.length > 0 ? (
          <div>
            <p className="mb-1.5 text-[11px] font-medium text-text-muted">
              {t('integrations.hub.rejectionReasons')}
            </p>
            <ul className="flex flex-wrap gap-1.5">
              {result.rejectionReasons.map((reason) => (
                <li key={reason.reason}>
                  <Badge tone="accent">
                    {t(`integrations.reason.${reason.reason}`)} · {num(reason.count)}
                  </Badge>
                </li>
              ))}
            </ul>
          </div>
        ) : null}

        {/* As received against as stored — the whole point of the mapping layer. */}
        <div>
          <p className="mb-1.5 text-[11px] font-medium text-text-muted">{t('integrations.hub.previewTitle')}</p>
          <p className="mb-2 text-[11px] text-text-faint">{t('integrations.hub.previewNote')}</p>
          <div className="space-y-2">
            {result.preview.map((record) => (
              <div key={`${record.assetCode}-${record.ts}`} className="rounded-lg border border-border bg-surface-2/40 p-3">
                <p className="font-mono text-[11px] text-text-muted">
                  {record.assetCode} · {formatDateTime(locale, record.ts)}
                </p>
                <ul className="mt-2 grid gap-1 sm:grid-cols-2">
                  {record.fields.map((field) => (
                    <li key={field.field} className="flex items-baseline justify-between gap-2 text-[11px]">
                      <span className="font-mono text-text-faint">{field.field}</span>
                      <span className="tabular-nums">
                        <span className="text-text-faint">
                          {String(field.sourceValue)} {field.sourceUnit}
                        </span>
                        <span className="mx-1.5 text-text-faint">→</span>
                        <span className="font-medium text-text">
                          {String(field.value)} {field.unit}
                        </span>
                      </span>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
        </div>
      </div>
    )
  }

  function Health({ detail: connector, sync: result }: { detail: ConnectorDetailView; sync: SyncResultView | null }) {
    const factors = result?.quality ?? connector.samples[connector.samples.length - 1] ?? null
    if (!factors) return <EmptyState title={t('uiState.empty')} body={t('integrations.hub.noEvents')} />

    const rows: Array<[string, number]> = [
      [t('integrations.hub.completeness'), factors.completeness],
      [t('integrations.hub.freshness'), factors.freshness],
      [t('integrations.hub.validity'), factors.validity],
      [t('integrations.hub.consistency'), factors.consistency],
      [t('integrations.hub.availability'), factors.availability],
      [t('integrations.hub.trust'), factors.trust],
    ]

    return (
      <div className="space-y-3" data-testid="integration-health">
        <p className="text-[11px] font-medium text-text-muted">{t('integrations.hub.qualityFactors')}</p>
        <div className="grid gap-2 sm:grid-cols-2">
          {rows.map(([label, value]) => (
            <Meter key={label} label={label} value={value} max={100} />
          ))}
        </div>
        {result ? (
          <p className="text-[11px] leading-relaxed text-text-muted">
            {t('integrations.hub.weakest')}: {t(`integrations.hub.${result.quality.weakest.key}`)} ·{' '}
            {num(result.quality.weakest.value, 1)}%. {t('integrations.hub.weakestNote')}
          </p>
        ) : null}
        {connector.mode === 'demo' ? (
          <p className="text-[11px] leading-relaxed text-text-faint">{t('integrations.hub.trustCapNote')}</p>
        ) : null}

        {/* Health history, plotted from the stored samples. */}
        <Sparkline points={connector.samples.map((sample) => sample.dataQuality)} />
      </div>
    )
  }

  function Events({ detail: connector }: { detail: ConnectorDetailView }) {
    if (connector.events.length === 0) {
      return <EmptyState title={t('uiState.empty')} body={t('integrations.hub.noEvents')} />
    }

    return (
      <ul className="space-y-1.5">
        {connector.events.map((event, index) => (
          <li
            key={`${event.ts}-${index}`}
            className="flex flex-wrap items-baseline justify-between gap-2 rounded-lg border border-border bg-surface-2/40 px-3 py-2 text-[11px]"
          >
            <span className="text-text-muted">{locale === 'ar' ? event.detailAr : event.detail}</span>
            <span className="font-mono tabular-nums text-text-faint">
              {num(event.latencyMs)} ms · {formatDateTime(locale, event.ts)}
            </span>
          </li>
        ))}
      </ul>
    )
  }

  function FaultPanel({
    detail: connector,
    canSimulate: allowed,
    busy: working,
    onSet,
  }: {
    detail: ConnectorDetailView
    canSimulate: boolean
    busy: boolean
    onSet: (kind: string) => void
  }) {
    return (
      <div className="space-y-3">
        <Notice tone="warning">{t('integrations.hub.faultNote')}</Notice>
        {connector.mode !== 'demo' ? (
          <Notice tone="danger">{t('integrations.hub.faultRefused')}</Notice>
        ) : allowed ? (
          <div className="flex flex-wrap gap-2">
            {FAULTS.map((fault) => (
              <Button
                key={fault}
                size="sm"
                variant={connector.faultKind === fault ? 'primary' : 'secondary'}
                disabled={working}
                onClick={() => onSet(fault)}
                data-fault={fault}
              >
                {t(`integrations.fault.${fault}`)}
              </Button>
            ))}
            <Button size="sm" variant="ghost" disabled={working || !connector.faultKind} onClick={() => onSet('')}>
              {t('integrations.hub.faultClear')}
            </Button>
          </div>
        ) : null}
      </div>
    )
  }

  function Sparkline({ points }: { points: number[] }) {
    if (points.length < 2) return null
    const min = Math.min(...points)
    const max = Math.max(...points)
    const span = Math.max(1, max - min)
    const path = points
      .map((value, index) => {
        const x = (index / (points.length - 1)) * 100
        const y = 30 - ((value - min) / span) * 26
        return `${index === 0 ? 'M' : 'L'}${x.toFixed(2)},${y.toFixed(2)}`
      })
      .join(' ')

    return (
      <figure>
        <figcaption className="mb-1 text-[11px] text-text-muted">
          {t('integrations.hub.healthHistory')} · {num(min, 1)}–{num(max, 1)}%
        </figcaption>
        <svg viewBox="0 0 100 32" preserveAspectRatio="none" className="h-16 w-full" role="img" aria-hidden="true">
          <path d={path} fill="none" stroke="currentColor" strokeWidth="1" className="text-brand" vectorEffect="non-scaling-stroke" />
        </svg>
      </figure>
    )
  }
}

function connectorLabelText(connector: ConnectorView, t: (key: string) => string): string {
  // The label the server derived, rendered through the locale. Never reassembled here:
  // a screen that rebuilt it from mode and status could rebuild it wrong.
  switch (connector.label) {
    case 'demo_connected':
      return t('integrations.hub.connected')
    case 'demo_degraded':
    case 'degraded':
      return t('integrations.hub.degraded')
    case 'demo_disconnected':
    case 'disconnected':
      return t('integrations.hub.disconnected')
    case 'demo_error':
    case 'error':
      return t('integrations.hub.errored')
    case 'connected':
      return t('integrations.status.connected')
    default:
      return connector.label
  }
}

function message(caught: unknown, t: (key: string) => string): string {
  return caught instanceof Error ? caught.message : t('common.error')
}
