import type { AdapterStatus, Item, Panel } from '../../src/lib/collector-types'
import { CI_PANEL } from './collector-fixtures'

const TS = '2025-07-18T00:53:20.000Z'

function ciPanelWithRepoPatch(repoName: string, patch: Record<string, unknown>): Panel {
  const panel = structuredClone(CI_PANEL)
  const data = panel.data as { repos: Array<Record<string, unknown>> }
  const repo = data.repos.find((entry) => entry.repo === repoName)
  if (!repo) throw new Error(`missing CI fixture repo: ${repoName}`)
  Object.assign(repo, patch)
  return panel
}

export const CI_PANEL_HISTORY_INCOMPLETE = ciPanelWithRepoPatch('alexcodeplace/multideal', {
  historyComplete: false,
  runs: [],
})

export const CI_PANEL_QUEUE_INCOMPLETE = ciPanelWithRepoPatch('alexcodeplace/multideal', {
  queueComplete: false,
})

export const CI_PANEL_QUEUE_NULL = ciPanelWithRepoPatch('alexcodeplace/multideal', {
  queueDepth: null,
})

export function ciPanelWithTrainGap(
  field: 'refsComplete' | 'prsComplete' | 'trainRunsComplete' | 'trainsComplete',
  stateGap: string,
): Panel {
  const panel = ciPanelWithRepoPatch('alexcodeplace/multideal', { [field]: false, trainsComplete: false })
  const data = panel.data as { repos: Array<Record<string, unknown>> }
  const repo = data.repos.find((entry) => entry.repo === 'alexcodeplace/multideal')!
  repo.trains = (repo.trains as Array<Record<string, unknown>>).map((train) => ({
    ...train,
    state: null,
    stateGap,
    gateRun: null,
    blockedBy: null,
    infraFlag: null,
  }))
  return panel
}

export const CI_PANEL_SIMULTANEOUS_INCOMPLETE = (() => {
  const panel = ciPanelWithTrainGap('refsComplete', 'train refs incomplete')
  const data = panel.data as Record<string, unknown> & { repos: Array<Record<string, unknown>> }
  data.runnersComplete = false
  const repo = data.repos.find((entry) => entry.repo === 'alexcodeplace/multideal')!
  Object.assign(repo, {
    queueComplete: false,
    historyComplete: false,
    trainRunsComplete: false,
    runnersComplete: false,
    prsComplete: false,
    trainsComplete: false,
    queueDepth: null,
    prQueueDepth: null,
    oldestQueuedAgeH: null,
    runnersBusy: null,
    runnersTotal: null,
  })
  repo.prs = (repo.prs as Array<Record<string, unknown>>).map((pr) => ({
    ...pr,
    checksComplete: false,
  }))
  return panel
})()

export const OFFLOAD_CONTROL_PANEL: Panel = {
  id: 'offload-control',
  ts: TS,
  data: {
    stale: false,
    desired: 'available',
    observed: 'available',
    revision: 4192,
    lease: { active: false, expired: false, host: null, expiresAt: null, reason: null },
    reconciler: { healthy: true, lastAt: '2026-07-18T06:14:00.000Z' },
    dispatch: { state: 'wedged', detail: 'slot-0 held by dead pid 2987388', host: 'debian1' },
    spill: { active: true, stale: true },
    capabilityByHost: {
      laptop: { probes: [{ name: 'full toolchain', ok: true }] },
      debian1: {
        probes: [
          { name: 'tsc', ok: true, version: '5.9.3' },
          { name: 'vitest', ok: true },
          { name: 'pnpm', ok: true },
          { name: 'playwright browsers', ok: false },
        ],
        circuitOpen: true,
        missingCommand: 'playwright browsers',
      },
      debian2: { probes: [] },
    },
  },
}

export const CLUSTER_QUEUE_PANEL: Panel = {
  id: 'cluster-queue',
  ts: TS,
  data: {
    stale: false,
    depth: 6,
    oldestAgeSeconds: 11520,
    p95AgeSeconds: 8,
    sloSeconds: 300,
    dispatchTarget: 'debian1',
    spill: { active: true, stale: true },
    wedge: { host: 'debian1', detail: 'slot-0 held by dead pid 2987388' },
    kpis: {
      remote24h: 2,
      remoteSuccessPct: 0,
      exit127: { count: 37, hosts: ['debian1'] },
    },
    tickets: [
      {
        position: 1,
        key: 'tsc-2279',
        repo: 'multideal',
        owner: { pid: 2279, starttime: 1721280000, label: 'claude·2279' },
        enqueueAgeSeconds: 11520,
        state: 'queued',
        dispatchTarget: 'debian1',
      },
      {
        position: 2,
        key: 'vitest-3341',
        repo: 'multideal',
        owner: { pid: 3341, starttime: 1721280240, label: 'claude·3341' },
        enqueueAgeSeconds: 11280,
        state: 'queued',
        dispatchTarget: 'debian1',
      },
    ],
  },
}

export const REMOTE_JOBS_PANEL: Panel = {
  id: 'remote-jobs',
  ts: TS,
  data: {
    stale: false,
    jobs: [
      {
        id: 'rb-8f2a1c',
        repo: 'multideal',
        snapshot: 'e3b1@4188',
        stage: 'building',
        host: 'debian1',
        rc: null,
        pullBytes: null,
        pullDurationSeconds: null,
        publication: { state: 'none' },
      },
      {
        id: 'rb-4e77b0',
        repo: 'zync',
        snapshot: '1f8e@4179',
        stage: 'failed',
        host: 'debian1',
        rc: 127,
        pullBytes: null,
        pullDurationSeconds: null,
        publication: { state: 'none', reason: 'tsc not found' },
      },
    ],
  },
}

export const FLEET_PANEL: Panel = {
  id: 'fleet',
  ts: TS,
  data: {
    stale: false,
    hosts: [
      {
        host: 'laptop',
        registryState: 'reachable',
        role: 'workstation',
        state: 'available',
        primary: false,
        enrolling: false,
        load: 16,
        cores: 16,
        coreLoads: [99, 97, 96, 94, 93, 91, 90, 89],
        running: 1,
        slotsFree: 3,
        slotsTotal: 4,
        builds24h: 9,
        sessions: 2,
        dispatchAccept: false,
        capability: { probes: [{ name: 'full toolchain', ok: true }] },
        memUsedBytes: 32_317_718_528,
        memTotalBytes: 34_359_738_368,
        swapUsedBytes: 4_509_949_952,
        swapTotalBytes: 8_589_934_592,
        netRxBytesPerSecond: 18_400_000,
        netTxBytesPerSecond: 2_100_000,
        disk: [
          { mountpoint: '/', freeBytes: 117_374_182_400, sizeBytes: 549_755_813_888 },
          { mountpoint: '/home', freeBytes: 133_946_818_560, sizeBytes: 549_755_813_888 },
        ],
        temp: { pkg: 79, max: 88, crit: 100 },
      },
      {
        host: 'debian1',
        registryState: 'reachable',
        role: 'builder',
        state: 'available',
        primary: true,
        enrolling: false,
        load: 3.9,
        cores: 8,
        coreLoads: [92, 88, 70, 45, 30, 22, 18, 10],
        running: 0,
        slotsFree: 8,
        slotsTotal: 8,
        builds24h: 214,
        sessions: 3,
        dispatchAccept: false,
        capability: {
          probes: [
            { name: 'tsc', ok: true, version: '5.9.3' },
            { name: 'vitest', ok: true },
            { name: 'pnpm', ok: true },
            { name: 'playwright browsers', ok: false },
          ],
          circuitOpen: true,
          missingCommand: 'playwright browsers',
        },
        memUsedBytes: 10_517_506_048,
        memTotalBytes: 34_359_738_368,
        swapUsedBytes: 0,
        swapTotalBytes: 8_589_934_592,
        netRxBytesPerSecond: 6_400_000,
        netTxBytesPerSecond: 46_327_808,
        disk: [{ mountpoint: '/', freeBytes: 95_443_783_680, sizeBytes: 536_870_912_000 }],
        temp: { pkg: 61, max: 66, crit: 95 },
        guard: {
          stall: { some60: 4.2, full60: 1.1, full300: 0.4 },
          tmpUsedBytes: 69_464_064,
          tmpSizeBytes: 16_714_129_408,
          workSlices: [
            { slice: 'agent.slice', memoryBytes: 3_221_225_472, pidsCurrent: 47, oomKillTotal: 2 },
            { slice: 'build.slice', memoryBytes: 0, pidsCurrent: 0, oomKillTotal: 0 },
          ],
        },
      },
      {
        host: 'debian2',
        registryState: 'reachable',
        role: 'builder',
        state: 'restoring',
        primary: false,
        enrolling: true,
        load: null,
        cores: null,
        coreLoads: [],
        running: null,
        slotsFree: null,
        slotsTotal: null,
        builds24h: null,
        sessions: null,
        dispatchAccept: null,
        capability: { probes: [] },
        memUsedBytes: null,
        memTotalBytes: null,
        swapUsedBytes: null,
        swapTotalBytes: null,
        netRxBytesPerSecond: null,
        netTxBytesPerSecond: null,
        disk: [],
        temp: { pkg: null, max: null, crit: null },
      },
    ],
  },
}

export const FLEET_PANEL_NORMAL_TEMP: Panel = {
  id: 'fleet',
  ts: TS,
  data: {
    stale: false,
    hosts: [
      {
        host: 'debian1',
        registryState: 'reachable',
        role: 'builder',
        state: 'available',
        primary: true,
        enrolling: false,
        load: 4.2,
        cores: 8,
        coreLoads: [45, 40, 35, 30, 25, 20, 15, 10],
        running: 1,
        slotsFree: 7,
        slotsTotal: 8,
        builds24h: 220,
        sessions: 1,
        dispatchAccept: true,
        capability: {
          probes: [
            { name: 'tsc', ok: true },
            { name: 'playwright browsers', ok: true },
          ],
        },
        memUsedBytes: 10_000_000_000,
        memTotalBytes: 34_359_738_368,
        swapUsedBytes: 0,
        swapTotalBytes: 8_589_934_592,
        netRxBytesPerSecond: 5_000_000,
        netTxBytesPerSecond: 40_000_000,
        disk: [{ mountpoint: '/', freeBytes: 100_000_000_000, sizeBytes: 536_870_912_000 }],
        temp: { pkg: 61, max: 66, crit: 95 },
      },
    ],
  },
}

export const FLEET_PANEL_CRIT_TEMP: Panel = {
  id: 'fleet',
  ts: TS,
  data: {
    stale: false,
    hosts: [
      {
        host: 'debian1',
        registryState: 'reachable',
        role: 'builder',
        state: 'available',
        primary: true,
        enrolling: false,
        load: 2.1,
        cores: 8,
        coreLoads: [95, 90, 85, 80, 75, 70, 65, 60],
        running: 0,
        slotsFree: 8,
        slotsTotal: 8,
        builds24h: 220,
        sessions: 1,
        dispatchAccept: false,
        capability: { probes: [{ name: 'tsc', ok: true }] },
        memUsedBytes: 10_000_000_000,
        memTotalBytes: 34_359_738_368,
        swapUsedBytes: 0,
        swapTotalBytes: 8_589_934_592,
        netRxBytesPerSecond: 5_000_000,
        netTxBytesPerSecond: 40_000_000,
        disk: [{ mountpoint: '/', freeBytes: 100_000_000_000, sizeBytes: 536_870_912_000 }],
        temp: { pkg: 96, max: 98, crit: 95 },
      },
    ],
  },
}

export const OFFLOAD_CONTROL_NORMAL: Panel = {
  id: 'offload-control',
  ts: TS,
  data: {
    stale: false,
    desired: 'available',
    observed: 'available',
    revision: 4200,
    lease: { active: false, expired: false, host: null },
    reconciler: { healthy: true, lastAt: '2026-07-18T12:00:00.000Z' },
    dispatch: { state: 'healthy' },
    capabilityByHost: {
      debian1: {
        probes: [
          { name: 'tsc', ok: true },
          { name: 'playwright browsers', ok: true },
        ],
      },
    },
  },
}

export const OFFLOAD_CONTROL_CRIT: Panel = {
  id: 'offload-control',
  ts: TS,
  data: {
    stale: false,
    desired: 'available',
    observed: 'available',
    revision: 4201,
    lease: { active: false, expired: false, host: null },
    reconciler: { healthy: true, lastAt: '2026-07-18T12:00:00.000Z' },
    dispatch: { state: 'healthy' },
    capabilityByHost: {
      debian1: { probes: [{ name: 'tsc', ok: true }] },
    },
  },
}

export const CLUSTER_QUEUE_EMPTY: Panel = {
  id: 'cluster-queue',
  ts: TS,
  data: {
    stale: false,
    depth: 0,
    oldestAgeSeconds: 0,
    p95AgeSeconds: 0,
    sloSeconds: 300,
    tickets: [],
  },
}

export const REMOTE_JOBS_EMPTY: Panel = {
  id: 'remote-jobs',
  ts: TS,
  data: { stale: false, jobs: [] },
}

export const CI_BUILD_INCIDENT_ITEMS: Item[] = [
  {
    id: 'offload:remote-idle-queue-stalled',
    source: 'offload',
    severity: 'act',
    kind: 'build',
    title: 'Remote capacity idle while queue is stalled',
    detail:
      '6 builds waiting (oldest 3h12m, SLO 5m); 8 builder slots idle. Queue: tsc-2279@multideal, vitest-3341@multideal, build-1187@platform',
    ts: TS,
    actions: [
      {
        verb: 'admission-reconcile',
        args: { expectedRevision: '4192' },
        label: 'Reconcile dispatch',
        recommended: true,
      },
      { verb: 'recall-spill', args: { expectedRevision: '4192' }, label: 'Recall laptop spill' },
    ],
  },
  {
    id: 'offload:capability-missing:debian1:playwright browsers',
    source: 'offload',
    severity: 'act',
    kind: 'build',
    title: 'Capability missing — 37× exit 127',
    detail: 'host debian1 · missing playwright browsers · jobs: rb-4e77b0, rb-3d66a1',
    ts: TS,
    actions: [
      {
        verb: 'host-quarantine',
        args: { host: 'debian1', command: 'playwright browsers', expectedRevision: '4192' },
        label: 'Quarantine host',
        recommended: true,
      },
    ],
  },
]

export const CI_BUILD_CRIT_TEMP_ITEM: Item = {
  id: 'offload:cpu-temp-critical:debian1',
  source: 'offload',
  severity: 'act',
  kind: 'build',
  title: 'CPU temperature critical — debian1',
  detail: 'Package temp 96°C ≥ critical 95°C; new dispatch paused until it clears.',
  ts: TS,
  actions: [
    {
      verb: 'box-drain',
      args: { host: 'debian1', expectedRevision: '4201' },
      label: 'Drain box',
      recommended: true,
    },
  ],
}

export const CI_BUILD_OFFLOAD_ADAPTER: AdapterStatus = {
  id: 'offload',
  interval: 30_000,
  lastAttempt: Date.parse(TS),
  lastSuccess: Date.parse(TS),
  consecutiveErrors: 0,
  stale: false,
}

export const CI_BUILD_INCIDENT_PANELS: Panel[] = [
  OFFLOAD_CONTROL_PANEL,
  CLUSTER_QUEUE_PANEL,
  REMOTE_JOBS_PANEL,
  FLEET_PANEL,
  CI_PANEL,
]

export const X1_OFFLOAD_VERBS = [
  'box-drain',
  'box-restore',
  'host-quarantine',
  'host-unquarantine',
  'admission-reconcile',
  'job-retry',
  'ci-reconcile',
  'recall-spill',
] as const

/** Read-only machine modal actions — not POSTed to the collector. */
export const READ_ONLY_MACHINE_VERBS = ['host-logs'] as const
