import { describe, it, expect } from 'vitest'
import { scoreMustHaves, MUST_HAVE_PENALTY_PER_MISS, MUST_HAVE_MAX_PENALTY } from '../mustHaveScorer'
import { makeProperty } from './fixtures'

// ── Empty criteria ─────────────────────────────────────────────────────────────

describe('scoreMustHaves — empty criteria', () => {
  it('returns zero impact and empty results when criteria list is empty', () => {
    const out = scoreMustHaves([], makeProperty())
    expect(out.results).toHaveLength(0)
    expect(Math.abs(out.scoreImpact)).toBe(0) // Math.abs handles JS -0 === +0
    expect(out.passedCount).toBe(0)
    expect(out.totalCount).toBe(0)
  })
})

// ── Erdgeschoss detection ──────────────────────────────────────────────────────

describe('scoreMustHaves — Erdgeschoss (ground floor)', () => {
  it('PASSES when property is floor 0 and criterion contains "erdgeschoss"', () => {
    const prop = makeProperty({ hardFacts: { floor: 0 } } as any)
    const out = scoreMustHaves(['Erdgeschoss erforderlich'], prop)
    expect(out.results[0].passed).toBe(true)
    expect(out.results[0].confidence).toBe('CERTAIN')
    expect(Math.abs(out.scoreImpact)).toBe(0) // no penalty for pass
  })

  it('FAILS when property is floor 1 and criterion contains "erdgeschoss"', () => {
    const prop = makeProperty({ hardFacts: { floor: 1 } } as any)
    const out = scoreMustHaves(['Erdgeschoss ist Pflicht'], prop)
    expect(out.results[0].passed).toBe(false)
    expect(out.results[0].confidence).toBe('CERTAIN')
    expect(out.scoreImpact).toBe(-MUST_HAVE_PENALTY_PER_MISS)
  })

  it('returns UNKNOWN confidence when floor field is not documented', () => {
    const prop = makeProperty() // no hardFacts in base fixture
    const out = scoreMustHaves(['Erdgeschoss'], prop)
    expect(out.results[0].confidence).toBe('UNKNOWN')
    expect(Math.abs(out.scoreImpact)).toBe(0) // UNKNOWN doesn't apply penalty
  })
})

// ── Klimaanlage detection ──────────────────────────────────────────────────────

describe('scoreMustHaves — Klimaanlage (air conditioning)', () => {
  it('PASSES when hasAirConditioning is true', () => {
    const prop = makeProperty({ hardFacts: { hasAirConditioning: true } } as any)
    const out = scoreMustHaves(['Klimaanlage vorhanden'], prop)
    expect(out.results[0].passed).toBe(true)
    expect(out.results[0].confidence).toBe('CERTAIN')
  })

  it('FAILS when hasAirConditioning is false', () => {
    const prop = makeProperty({ hardFacts: { hasAirConditioning: false } } as any)
    const out = scoreMustHaves(['Air conditioning benötigt'], prop)
    expect(out.results[0].passed).toBe(false)
    expect(out.results[0].confidence).toBe('CERTAIN')
    expect(out.scoreImpact).toBe(-MUST_HAVE_PENALTY_PER_MISS)
  })

  it('returns UNKNOWN when AC data is missing', () => {
    const prop = makeProperty()
    const out = scoreMustHaves(['HVAC Anlage'], prop)
    expect(out.results[0].confidence).toBe('UNKNOWN')
  })
})

// ── Laderampe detection ───────────────────────────────────────────────────────

describe('scoreMustHaves — Laderampe (loading dock)', () => {
  it('PASSES when loadingDocksCount >= 1', () => {
    const prop = makeProperty({ hardFacts: { loadingDocksCount: 2 } } as any)
    const out = scoreMustHaves(['Laderampe erforderlich'], prop)
    expect(out.results[0].passed).toBe(true)
  })

  it('FAILS when loadingDocksCount is 0', () => {
    const prop = makeProperty({ hardFacts: { loadingDocksCount: 0 } } as any)
    const out = scoreMustHaves(['Verladerampe oder Tor'], prop)
    expect(out.results[0].passed).toBe(false)
    expect(out.scoreImpact).toBe(-MUST_HAVE_PENALTY_PER_MISS)
  })
})

// ── Parking with minimum count ────────────────────────────────────────────────

describe('scoreMustHaves — Parkplatz with minimum count', () => {
  it('PASSES when available parking >= required count', () => {
    const prop = makeProperty({ softFactors: { ...makeProperty().softFactors, parkingSpots: 6 } as any })
    const out = scoreMustHaves(['mind. 5 Parkplätze'], prop)
    expect(out.results[0].passed).toBe(true)
    expect(out.results[0].confidence).toBe('CERTAIN')
    expect(out.results[0].explanation).toMatch(/vorhanden/)
  })

  it('FAILS when available parking < required count', () => {
    const prop = makeProperty({ softFactors: { ...makeProperty().softFactors, parkingSpots: 3 } as any })
    const out = scoreMustHaves(['mind. 10 Parkplätze'], prop)
    expect(out.results[0].passed).toBe(false)
    expect(out.results[0].confidence).toBe('CERTAIN')
    expect(out.scoreImpact).toBe(-MUST_HAVE_PENALTY_PER_MISS)
  })

  it('detects parking keyword without numeric count', () => {
    const prop = makeProperty({ softFactors: { ...makeProperty().softFactors, parkingSpots: 2 } as any })
    const out = scoreMustHaves(['Parkplatz vorhanden'], prop)
    expect(out.results[0].passed).toBe(true)
  })
})

// ── Penalty accumulation and cap ─────────────────────────────────────────────

describe('scoreMustHaves — penalty accumulation and cap', () => {
  it(`applies -${MUST_HAVE_PENALTY_PER_MISS} per failed CERTAIN criterion`, () => {
    const prop = makeProperty({
      hardFacts: { hasAirConditioning: false, loadingDocksCount: 0 },
    } as any)
    const out = scoreMustHaves(['Klimaanlage', 'Laderampe'], prop)
    expect(out.scoreImpact).toBe(-2 * MUST_HAVE_PENALTY_PER_MISS)
  })

  it(`caps total penalty at -${MUST_HAVE_MAX_PENALTY}`, () => {
    const prop = makeProperty({
      hardFacts: {
        hasAirConditioning: false,
        loadingDocksCount: 0,
        floor: 2,
        isBarrierFree: false,
      },
    } as any)
    const out = scoreMustHaves([
      'Klimaanlage',
      'Laderampe',
      'Erdgeschoss erforderlich',
      'Barrierefrei',
    ], prop)
    expect(out.scoreImpact).toBeGreaterThanOrEqual(-MUST_HAVE_MAX_PENALTY)
    expect(out.scoreImpact).toBeLessThanOrEqual(0)
  })

  it('UNKNOWN criteria do not contribute to scoreImpact', () => {
    // No hardFacts on base fixture → Klimaanlage and Laderampe return UNKNOWN
    const out = scoreMustHaves(['Klimaanlage', 'Laderampe'], makeProperty())
    expect(Math.abs(out.scoreImpact)).toBe(0)
  })
})

// ── Unrecognized criterion ────────────────────────────────────────────────────

describe('scoreMustHaves — unrecognized criterion', () => {
  it('returns UNKNOWN and false for an unrecognized criterion string', () => {
    const out = scoreMustHaves(['Einzigartiges Sonderkriterium XYZ'], makeProperty())
    expect(out.results[0].confidence).toBe('UNKNOWN')
    expect(out.results[0].passed).toBe(false)
    expect(Math.abs(out.scoreImpact)).toBe(0)
  })
})
