import { describe, expect, it } from 'vitest'
import { ciKvRows, isActivePlanRun, planKvRows, sortPlanRunsForOverview } from './overview-mappers'
import type { GhciPanelData, HarnessPlanRun } from './panel-data'

function planRun(overrides: Partial<HarnessPlanRun> & Pick<HarnessPlanRun, 'runId' | 'title' | 'status'>): HarnessPlanRun {
  return {
    seq: 1,
    state: 'active',
    owner: 'harness',
    currentTask: null,
    tasksTotal: 1,
    tasksCompleted: 0,
    pendingDecisions: 0,
    degradedReason: '',
    updatedAt: null,
    repoRoot: '/tmp',
    abandoned: false,
    abandonedAt: null,
    waves: [],
    ...overrides,
  }
}

describe('ciKvRows', () => {
  it('renders offline runners with err intent', () => {
    const data: GhciPanelData = {
      runners: [],
      runnersComplete: true,
      oldestQueuedAgeH: null,
      repos: [
        {
          repo: 'alexcodeplace/multideal',
          degraded: [],
          queueComplete: true,
          historyComplete: true,
          refsComplete: true,
          trainRunsComplete: true,
          runnersComplete: true,
          prsComplete: true,
          trainsComplete: true,
          queueDepth: 0,
          runs: [],
          runners: [{ id: 1, name: 'multideal-debian1', status: 'offline', busy: false, currentJob: null, currentRepo: null, currentKnown: true }],
          runnersBusy: 0,
          runnersTotal: 1,
          prQueueDepth: 0,
          oldestQueuedAgeH: null,
          prs: [],
          trains: [],
          lag: { landsToday: null, medianOpenToMergeH7d: null, gates: [], warmedAt: null },
        },
      ],
    }

    const rows = ciKvRows(data)
    expect(rows.find((row) => row.label === 'multideal-debian1')).toMatchObject({
      value: 'offline',
      intent: 'err',
    })
  })
})

describe('sortPlanRunsForOverview', () => {
  it('puts running plans first, then most-recent activity', () => {
    const runs = sortPlanRunsForOverview([
      planRun({ runId: 'old-done', title: 'old-done', status: 'completed', updatedAt: '2026-07-21T10:00:00.000Z' }),
      planRun({ runId: 'running', title: 'running', status: 'running', updatedAt: '2026-07-21T08:00:00.000Z', tasksTotal: 4, tasksCompleted: 2 }),
      planRun({ runId: 'fresh-done', title: 'fresh-done', status: 'completed', updatedAt: '2026-07-21T12:00:00.000Z' }),
    ])

    expect(runs.map((run) => run.runId)).toEqual(['running', 'fresh-done', 'old-done'])
  })

  it('drops stale running plans with all tasks complete below active work', () => {
    const runs = sortPlanRunsForOverview([
      planRun({
        runId: 'stale-running',
        title: 'stale-running',
        status: 'running',
        updatedAt: '2026-07-21T12:00:00.000Z',
        tasksTotal: 6,
        tasksCompleted: 6,
      }),
      planRun({
        runId: 'in-progress',
        title: 'in-progress',
        status: 'running',
        updatedAt: '2026-07-21T08:00:00.000Z',
        tasksTotal: 4,
        tasksCompleted: 2,
      }),
      planRun({
        runId: 'gated',
        title: 'gated',
        status: 'gated',
        updatedAt: '2026-07-21T10:00:00.000Z',
        tasksTotal: 5,
        tasksCompleted: 4,
      }),
    ])

    expect(runs.map((run) => run.runId)).toEqual(['gated', 'in-progress', 'stale-running'])
    expect(isActivePlanRun(runs[2]!)).toBe(false)
  })
})

describe('planKvRows', () => {
  it('preserves the overview sort order', () => {
    const rows = planKvRows({
      runs: [
        planRun({ runId: 'old-done', title: 'old-done', status: 'completed', updatedAt: '2026-07-21T10:00:00.000Z' }),
        planRun({
          runId: 'running',
          title: 'running',
          status: 'running',
          updatedAt: '2026-07-21T08:00:00.000Z',
          tasksTotal: 4,
          tasksCompleted: 2,
        }),
      ],
    })

    expect(rows.map((row) => row.label)).toEqual(['running', 'old-done'])
  })
})
