import { describe, expect, it } from 'vitest'

import {
  ESTIMATE_LABELS,
  extractLabelFacts,
  parseEstimateLabel,
  parsePriorityLabel,
} from './label-schema.js'

describe('parseEstimateLabel', () => {
  it.each([
    ['est/1d', 1],
    ['est/2d', 2],
    ['est/3d', 3],
    ['est/5d', 5],
    ['est/8d', 8],
  ])('parses %s → %i days', (label, days) => {
    expect(parseEstimateLabel(label)).toBe(days)
  })

  it('rejects estimates outside the fixed set', () => {
    expect(parseEstimateLabel('est/4d')).toBeNull()
    expect(parseEstimateLabel('est/13d')).toBeNull()
    expect(parseEstimateLabel('est/3h')).toBeNull()
    expect(parseEstimateLabel('EST/3d')).toBeNull()
  })
})

describe('parsePriorityLabel', () => {
  it('parses p/1 through p/4', () => {
    expect(parsePriorityLabel('p/1')).toBe(1)
    expect(parsePriorityLabel('p/4')).toBe(4)
  })

  it('rejects out-of-range and malformed priorities', () => {
    expect(parsePriorityLabel('p/0')).toBeNull()
    expect(parsePriorityLabel('p/5')).toBeNull()
    expect(parsePriorityLabel('P/1')).toBeNull()
    expect(parsePriorityLabel('priority/1')).toBeNull()
  })
})

describe('extractLabelFacts', () => {
  it('extracts all three axes from a full label set', () => {
    const facts = extractLabelFacts(['est/3d', 'p/2', 'deadline/hard', 'bug'])
    expect(facts).toEqual({
      estimateDays: 3,
      priority: 2,
      hardDeadline: true,
      malformed: [],
      conflicts: [],
    })
  })

  it('ignores labels outside CommiTea namespaces entirely', () => {
    const facts = extractLabelFacts(['bug', 'enhancement', 'wontfix'])
    expect(facts.estimateDays).toBeNull()
    expect(facts.priority).toBeNull()
    expect(facts.malformed).toEqual([])
  })

  it('reports in-namespace labels that fail to parse as malformed', () => {
    const facts = extractLabelFacts(['est/4d', 'p/9', 'deadline/soft'])
    expect(facts.malformed).toEqual(['est/4d', 'p/9', 'deadline/soft'])
    expect(facts.estimateDays).toBeNull()
    expect(facts.priority).toBeNull()
    expect(facts.hardDeadline).toBe(false)
  })

  it('resolves estimate conflicts pessimistically and reports them', () => {
    const facts = extractLabelFacts(['est/2d', 'est/8d'])
    expect(facts.estimateDays).toBe(8)
    expect(facts.conflicts).toEqual(['est/8d'])
  })

  it('resolves priority conflicts toward urgency and reports them', () => {
    const facts = extractLabelFacts(['p/3', 'p/1'])
    expect(facts.priority).toBe(1)
    expect(facts.conflicts).toEqual(['p/1'])
  })

  it('handles the empty label list', () => {
    expect(extractLabelFacts([])).toEqual({
      estimateDays: null,
      priority: null,
      hardDeadline: false,
      malformed: [],
      conflicts: [],
    })
  })

  it('keeps the fixed estimate set in sync with its parser', () => {
    for (const label of ESTIMATE_LABELS) {
      expect(parseEstimateLabel(label)).not.toBeNull()
    }
  })
})
