-- RLDiseaseTests.lua
-- Purpose: Tests for Disease.modifyValue() and Disease.modifyOutput()
--          using plain table mocks (no Disease.new() or setmetatable)
-- Author: Ritter

RLDiseaseTests = {}

local Log = RmLogging.getLogger("RLRM")

--- Run all disease tests
---@param assert function Assert closure from RLTestRunner
function RLDiseaseTests:runAll(assert)
    Log:info("--- Disease Tests ---")

    -- Save state
    local savedDiseasesEnabled = g_diseaseManager.diseasesEnabled

    -- Ensure diseases are enabled for most tests
    g_diseaseManager.diseasesEnabled = true

    -- =========================================================================
    -- modifyValue
    -- =========================================================================

    local mvMock1 = { type = { value = 0.8 } }
    local mv1 = Disease.modifyValue(mvMock1, 100)
    assert("modifyValue 0.8 multiplier", mv1 == 80, 80, mv1)

    local mvMock2 = { type = { value = 1.0 } }
    local mv2 = Disease.modifyValue(mvMock2, 100)
    assert("modifyValue 1.0 returns unchanged", mv2 == 100, 100, mv2)

    local mvMock3 = { type = { value = 0.0 } }
    local mv3 = Disease.modifyValue(mvMock3, 100)
    assert("modifyValue 0.0 returns 0", mv3 == 0, 0, mv3)

    -- =========================================================================
    -- modifyOutput — active disease
    -- =========================================================================

    local moActive = { cured = false, isCarrier = false, type = { output = { milk = 0.5 } } }
    local mo1 = Disease.modifyOutput(moActive, "milk", 100)
    assert("modifyOutput active disease milk=0.5", mo1 == 50, 50, mo1)

    -- =========================================================================
    -- modifyOutput — cured (returns value unchanged)
    -- =========================================================================

    local moCured = { cured = true, isCarrier = false, type = { output = { milk = 0.5 } } }
    local mo2 = Disease.modifyOutput(moCured, "milk", 100)
    assert("modifyOutput cured returns unchanged", mo2 == 100, 100, mo2)

    -- =========================================================================
    -- modifyOutput — carrier with carrier.output
    -- =========================================================================

    local moCarrier = {
        cured = false, isCarrier = true,
        type = { carrier = { output = { milk = 0.9 } }, output = { milk = 0.5 } }
    }
    local mo3 = Disease.modifyOutput(moCarrier, "milk", 100)
    assert("modifyOutput carrier uses carrier multiplier", mo3 == 90, 90, mo3)

    -- =========================================================================
    -- modifyOutput — carrier without carrier table (falls through to disease output)
    -- =========================================================================

    local moCarrierNil = {
        cured = false, isCarrier = true,
        type = { carrier = nil, output = { milk = 0.5 } }
    }
    local mo4 = Disease.modifyOutput(moCarrierNil, "milk", 100)
    assert("modifyOutput carrier without carrier table falls through", mo4 == 50, 50, mo4)

    -- =========================================================================
    -- modifyOutput — nil output key (fallback `or 1`)
    -- =========================================================================

    local moNilKey = { cured = false, isCarrier = false, type = { output = {} } }
    local mo5 = Disease.modifyOutput(moNilKey, "eggs", 100)
    assert("modifyOutput nil output key returns unchanged", mo5 == 100, 100, mo5)

    -- =========================================================================
    -- modifyOutput — diseases disabled
    -- =========================================================================

    g_diseaseManager.diseasesEnabled = false
    local moDisabled = { cured = false, isCarrier = false, type = { output = { milk = 0.5 } } }
    local mo6 = Disease.modifyOutput(moDisabled, "milk", 100)
    assert("modifyOutput disabled returns unchanged", mo6 == 100, 100, mo6)

    -- =========================================================================
    -- getHasAnyDisease — nil g_diseaseManager guard
    -- =========================================================================

    self:testGetHasAnyDiseaseNilGuard(assert)

    -- Restore state
    g_diseaseManager.diseasesEnabled = savedDiseasesEnabled
end


--- Test that Animal:getHasAnyDisease() returns false when g_diseaseManager is nil.
---@param assert function Assert closure from RLTestRunner
function RLDiseaseTests:testGetHasAnyDiseaseNilGuard(assert)
    Log:info("--- getHasAnyDisease nil-guard ---")

    local savedManager = g_diseaseManager

    -- Mock animal with diseases
    local mockAnimal = { diseases = { {}, {} } }

    -- Normal case: diseases enabled + has diseases → true
    g_diseaseManager = savedManager
    g_diseaseManager.diseasesEnabled = true
    local result1 = Animal.getHasAnyDisease(mockAnimal)
    assert("getHasAnyDisease returns true when enabled with diseases", result1 == true, true, result1)

    -- Nil g_diseaseManager → false (no crash)
    g_diseaseManager = nil
    local result2 = Animal.getHasAnyDisease(mockAnimal)
    assert("getHasAnyDisease returns false when g_diseaseManager nil", result2 == false, false, result2)

    -- Restore
    g_diseaseManager = savedManager
end
