import { describe, expect, it } from 'vitest'
import type { Item } from '../../lib/collector-types'
import {
  expandedContentForItem,
  factoryDecisionId,
  isDecisionQueueItem,
  isFactoryDecisionItem,
  isHaltItem,
  isPermissionItem,
  optionsForItem,
} from './decision-mappers'

function item(overrides: Partial<Item>): Item {
  return {
    id: 'harness-decision-1',
    source: 'harness',
    severity: 'act',
    kind: 'decision',
    title: 'Pick',
    detail: 'detail',
    ts: '2026-08-05T11:00:00Z',
    actions: [],
    ...overrides,
  }
}

describe('decision mappers', () => {
  it('separates decisions from halts', () => {
    expect(isDecisionQueueItem(item({ kind: 'decision' }))).toBe(true)
    expect(isDecisionQueueItem(item({ kind: 'halt' }))).toBe(false)
    expect(isHaltItem(item({ kind: 'halt' }))).toBe(true)
    expect(isHaltItem(item({ kind: 'decision' }))).toBe(false)
  })

  it('renders options for both harness and factory answer verbs', () => {
    const harness = item({
      actions: [{ verb: 'harness.decision.answer', args: { choice: 'yes' }, label: 'Yes' }],
    })
    const factory = item({
      id: 'factory-decision-dec-9',
      source: 'factory',
      actions: [{ verb: 'factory.decision.answer', args: { decisionId: 'dec-9', choice: 'a' }, label: 'A', recommended: true }],
    })
    const other = item({ actions: [{ verb: 'reap', args: {}, label: 'Reap' }] })

    expect(optionsForItem(harness)).toEqual([{ label: 'Yes', recommended: undefined, choice: 'yes' }])
    expect(optionsForItem(factory)).toEqual([{ label: 'A', recommended: true, choice: 'a' }])
    expect(optionsForItem(other)).toEqual([])
  })

  it('identifies factory decision items by id prefix and extracts the decision id', () => {
    const factory = item({ id: 'factory-decision-dec-9', source: 'factory' })
    expect(isFactoryDecisionItem(factory)).toBe(true)
    expect(factoryDecisionId(factory)).toBe('dec-9')
    expect(isFactoryDecisionItem(item({}))).toBe(false)
  })

  it('renders allow/deny options for a queued tool permission and offers no free text', () => {
    const permission = item({
      id: 'permission:abc:1',
      source: 'permissions',
      title: 'Bash — awaiting approval',
      actions: [
        { verb: 'permission.answer', args: { requestId: 'permission:abc:1', choice: 'allow' }, label: 'Allow' },
        { verb: 'permission.answer', args: { requestId: 'permission:abc:1', choice: 'deny' }, label: 'Deny' },
      ],
      decision: {
        question: 'Allow Bash in /repo?',
        options: [{ label: 'Allow' }, { label: 'Deny' }],
        freeText: false,
        context: '{"dataBlock":"{}"}',
        waitingSince: '2026-08-05T11:00:00Z',
      },
    })

    expect(isPermissionItem(permission)).toBe(true)
    expect(isPermissionItem(item({}))).toBe(false)
    expect(optionsForItem(permission).map((option) => option.choice)).toEqual(['allow', 'deny'])
    expect(expandedContentForItem(permission).allowFreeText).toBe(false)
  })

  it('allows free text on factory items only when the decision declares it', () => {
    const decision = { question: 'q', options: [], context: '', waitingSince: '2026-08-05T11:00:00Z' }
    const factoryNoFree = item({ id: 'factory-decision-1', decision: { ...decision, freeText: false } })
    const factoryFree = item({ id: 'factory-decision-2', decision: { ...decision, freeText: true } })
    const harnessNoDecision = item({})

    expect(expandedContentForItem(factoryNoFree).allowFreeText).toBe(false)
    expect(expandedContentForItem(factoryFree).allowFreeText).toBe(true)
    expect(expandedContentForItem(harnessNoDecision).allowFreeText).toBe(true)
  })
})
