import { describe, expect, it } from 'vitest'
import type { FactoryAgentAttemptView } from '../../lib/factory-types'
import { deriveAgentInputPresentation } from './AgentInputPanel'

function attempt(overrides: Partial<FactoryAgentAttemptView> = {}): FactoryAgentAttemptView {
  return { attemptId: 'attempt', phaseId: 'phase', agent: 'builder', sessionId: 'session', command: null, systemPrompt: null, userPrompt: null, returncode: null, signal: null, timedOut: false, tokens: null, usage: null, providerFailure: null, error: null, stderrPath: null, host: null, account: null, model: null, startedAt: '2026-08-10T10:00:00.000Z', lastOutputAt: null, endedAt: null, durationMs: null, idleMs: null, ...overrides }
}
function template(task: string): string { return `# Build Task\n\n### prompt\n${task}\n### previous_envelope\n{}` }

describe('deriveAgentInputPresentation', () => {
  it('extracts a byte-preserving known template body', () => {
    const value = '  leading\n\n# task\ntrailing  '
    const result = deriveAgentInputPresentation(attempt({ userPrompt: template(value) }), [])
    expect(result.taskText).toBe(value)
    expect(result.taskSource).toBe('known_template')
    expect(result.ambiguity).toBeNull()
  })

  it.each([
    '# Unknown Task\n### prompt\ntask\n### previous_envelope',
    '# Build Task\n### prompt\na\n### prompt\nb\n### previous_envelope',
    '# Build Task\n### previous_envelope\na\n### prompt',
    '# Build Task\n### prompt\na',
  ])('falls back to the exact message for ambiguous templates', (userPrompt) => {
    const result = deriveAgentInputPresentation(attempt({ userPrompt }), [])
    expect(result.taskText).toBe(userPrompt)
    expect(result.taskSource).toBe('exact_current_message')
    expect(result.ambiguity).toBe('The stable task or inherited context could not be separated from this message.')
  })

  it('does not mistake a recognized title inside an unknown prompt body for the wrapper', () => {
    const userPrompt = '# Unknown Task\n\n### prompt\n# Build Task\nbody\n### previous_envelope\n{}'
    const result = deriveAgentInputPresentation(attempt({ userPrompt }), [])
    expect(result.taskSource).toBe('exact_current_message')
    expect(result.taskText).toBe(userPrompt)
    expect(result.ambiguity).toBe('The stable task or inherited context could not be separated from this message.')
  })

  it('keeps recorded inherited context when the user message is absent', () => {
    const result = deriveAgentInputPresentation(attempt({ userPrompt: null }), [attempt({ attemptId: 'prior', startedAt: '2026-08-10T09:00:00.000Z', userPrompt: template('old') })])
    expect(result).toMatchObject({ taskText: '', currentMessage: null, ambiguity: null })
    expect(result.priorTurns.map((turn) => turn.attemptId)).toEqual(['prior'])
  })

  it('orders only same-session earlier run turns and excludes null sessions', () => {
    const selected = attempt({ attemptId: 'selected', startedAt: '2026-08-10T10:00:00.000Z', userPrompt: template('task') })
    const result = deriveAgentInputPresentation(selected, [
      attempt({ attemptId: 'b', startedAt: '2026-08-10T09:00:00.000Z', userPrompt: 'b' }),
      attempt({ attemptId: 'a', startedAt: '2026-08-10T09:00:00.000Z', userPrompt: 'a' }),
      attempt({ attemptId: 'other', sessionId: 'other', startedAt: '2026-08-10T08:00:00.000Z' }),
      attempt({ attemptId: 'null', sessionId: null, startedAt: '2026-08-10T08:00:00.000Z' }),
    ])
    expect(result.priorTurns.map((turn) => turn.attemptId)).toEqual(['a', 'b'])
  })

  it('uses the nearest eligible same-phase known task for a correction', () => {
    const selected = attempt({ attemptId: 'correction', userPrompt: 'Fix the test failure.', startedAt: '2026-08-10T12:00:00.000Z' })
    const result = deriveAgentInputPresentation(selected, [
      attempt({ attemptId: 'old', userPrompt: template('old task'), startedAt: '2026-08-10T10:00:00.000Z' }),
      attempt({ attemptId: 'near', userPrompt: template('stable task'), startedAt: '2026-08-10T11:00:00.000Z' }),
      attempt({ attemptId: 'other-phase', phaseId: 'other', userPrompt: template('wrong task'), startedAt: '2026-08-10T11:30:00.000Z' }),
    ])
    expect(result).toMatchObject({ taskText: 'stable task', taskSource: 'prior_turn', currentMessage: 'Fix the test failure.', ambiguity: null })
  })

  it('does not skip equal or invalid ordering to recover an older task', () => {
    const selected = attempt({ userPrompt: 'Correction', startedAt: '2026-08-10T10:00:00.000Z' })
    const older = attempt({ attemptId: 'older', userPrompt: template('older task'), startedAt: '2026-08-10T08:00:00.000Z' })
    const equal = attempt({ attemptId: 'equal', userPrompt: template('equal task'), startedAt: '2026-08-10T10:00:00.000Z' })
    const invalid = attempt({ attemptId: 'invalid', userPrompt: template('invalid task'), startedAt: 'invalid' })
    expect(deriveAgentInputPresentation(selected, [older, equal]).taskSource).toBe('exact_current_message')
    expect(deriveAgentInputPresentation(selected, [older, invalid]).taskSource).toBe('exact_current_message')
    expect(deriveAgentInputPresentation(attempt({ userPrompt: 'Correction', startedAt: 'invalid' }), [older]).taskSource).toBe('exact_current_message')
  })
})
