const MULTIPLIERS = {
    "Rainbow": 50,
    "Golden": 20,
    "Frozen": 10,
    "Bloodlit": 4,
    "Pollinated": 3,
    "Wet": 2,
    "Chilled": 2
};

const BASELINE_GOLDEN_CHANCE = 0.01; // 1.0%

class Decision {

    /**
     * @param {Object} crop - { species, baseValue, scale, mutations: [] }
     * @param {Object} worldEvents - { 
     *   Time_Until_Next_Event_Hrs, 
     *   Time_Assuming_Growth_Speed_Boost,
     *   Time_Remaining_Hrs,
     *   P_Next_Rain_Thunderstorm, 
     *   P_Next_Frost, 
     *   Time_To_Next_Blood_Moon_Hrs,
     *   Event_Active
     * }
     */
    static shouldHarvest(crop, worldEvents) {
        // Step 3.1: Deterministic Value (V_HarvestNow)
        const vHarvestNow = this.calculateDeterministicValue(crop);

        // Step 3.2: Growth Progression & Time Compression
        // Delta T effective
        // If Event_Active is true, speed is 1.5x, else 1.0x
        const speedMultiplier = worldEvents.Event_Active ? 1.5 : 1.0;
        const deltaTEff = worldEvents.Time_Until_Next_Event_Hrs * speedMultiplier;

        const tRemNext = worldEvents.Time_Remaining_Hrs - deltaTEff;

        // Critical Check: If crop matures during wait, harvest NOW (continuing value is capped/complicated)
        // Ignoring complicated capped value logic for now as per instructions "E is capped" -> imply we might just harvest?
        // Actually instructions say: "If T_rem <= 0 ... calculation focuses only on expected mutation gains over Delta t"
        // But usually if it matures, we might as well harvest or we risk rotting? 
        // For this V1 implementation, if it matures, let's assume we proceed with E calculation but T_rem is 0.
        // However, the prompt says "If T_rem > 0, the harvest is delayed". Implicitly if <=0, maybe we consider it 'mature' state.
        // Let's stick to the prompt's implied logic for now: calculate E regardless, but note the state.

        // Step 3.3: Stochastic Transition Value (E)
        const E = this.calculateStochasticTransition(crop, vHarvestNow, worldEvents);

        // Step 3.4: Strategic Interval Check (Blood Moon)
        let maxE = E;
        let strategy = "Standard Wait";

        // Check if we can wait for Blood Moon
        // Use simplified logic: if generic wait leaves us with time, AND we have enough time for BM
        // Note: T_rem(t + Delta_t) > 0 check from prompt
        if (tRemNext > 0 && worldEvents.Time_To_Next_Blood_Moon_Hrs <= worldEvents.Time_Remaining_Hrs) {
            const eBM = this.calculateBloodMoonValue(vHarvestNow);
            if (eBM > E) {
                maxE = eBM;
                strategy = "Blood Moon Wait";
            }
        }

        // Step 3.5: Optimal Decision Synthesis
        const decision = {
            action: vHarvestNow >= maxE ? "HARVEST_NOW" : "WAIT",
            vHarvestNow: vHarvestNow,
            expectedValue: maxE,
            strategy: strategy,
            details: {
                E_Standard: E,
                tRemNext: tRemNext
            }
        };

        return decision;
    }

    static calculateDeterministicValue(crop) {
        let multiplier = 1.0;
        if (crop.mutations) {
            crop.mutations.forEach(m => {
                const val = MULTIPLIERS[m] || 1.0; // Default to 1 if unknown or wait? Assume multiplicative
                multiplier *= val;
            });
        }
        // Base Value * Mass * Multipliers
        // Mass is 'scale'
        return (crop.baseValue || 1) * (crop.scale || 1) * multiplier;
    }

    static calculateStochasticTransition(crop, vNow, worldEvents) {
        const mutations = new Set(crop.mutations || []);

        // A. Rain/Thunderstorm
        // Base Gain: 50% chance of Wet (2x)
        // Fusion: If Chilled present, Wet can fuse to Frozen (10x). Chilled (2x) is lost.
        //   Fusion Logic: "Rain ... has a chance to fuse it" - let's assume 100% chance IF Rain happens for this calculation?
        //   Prompt says: "If Chilled is present, Rain... has a chance". Let's assume the event IS Rain.
        //   Wait, structure is: E = P_Rain * V_Rain + ...
        //   Inside V_Rain: What is the gain?
        //   Prompt: "1. Calculate expected fusion gain factor".
        //   Assumption: If 'Chilled' exists, 2x becomes 10x? Or is it 50% chance?
        //   Prompt says "Rain... has a chance". Usually fusion is guaranteed if conditions met in these games?
        //   Let's assume for V1: If Rain hits, and Chilled exists => Frozen (10x).
        //   If Chilled NOT exists => Wet (2x) with 50% chance.

        let multiplierGainA = 1.0;
        if (mutations.has("Chilled")) {
            // Fusion: Chilled (2x) -> Frozen (10x). Gain factor = 10 / 2 = 5x?
            // Wait, vNow already includes Chilled(2x).
            // New Multiplier Product would be: (Old_Prod / 2) * 10 = Old_Prod * 5.
            // So Gain Factor is 5.
            // Probability of fusion? "has a chance". Let's assume 100% GIVEN Rain for now, or 50%?
            // "Base Gain: 50% chance of 2x Wet".
            // Let's assume Fusion is also 50% chance if Chilled is there? Or maybe the event IS the fusion?
            // Let's use 50% for fusion chance given Rain.
            multiplierGainA = 1.0 + 0.5 * (5.0 - 1.0); // Exp Value of factor? 
            // Actually, let's look at value: 
            // avg_mult = 0.5 * 5 (Fusion) + 0.5 * 1 (Nothing) = 3.0 relative to current? 
            // No, if nothing happens, it stays 1.0.
            // So E[Factor] = 0.5 * 5 + 0.5 * 1 = 3.0?
        } else {
            // Wet (2x). Gain from 1.0 to 2.0.
            // If we already have Wet? Usually mutations are unique?
            // Prompt says "Identify all current, UNIQUE mutations".
            // If we have Wet, can we get double Wet? Assume No.
            if (!mutations.has("Wet") && !mutations.has("Frozen")) { // Assuming Frozen prevents Wet?
                multiplierGainA = 1.0 + 0.5 * (2.0 - 1.0); // 0.5 * 2 + 0.5 * 1 = 1.5
            }
        }
        const V_A = vNow * multiplierGainA;

        // B. Frost
        // Base Gain: 50% chance of Chilled (2x).
        // Fusion: If Wet present -> Frozen (10x). Replaces Wet (2x).
        let multiplierGainB = 1.0;
        if (mutations.has("Wet")) {
            // Fusion: Wet(2x) -> Frozen(10x). Factor = 5.
            // Chance: 50%?
            multiplierGainB = 1.0 + 0.5 * (5.0 - 1.0); // 3.0
        } else {
            if (!mutations.has("Chilled") && !mutations.has("Frozen")) {
                multiplierGainB = 1.0 + 0.5 * (2.0 - 1.0); // 1.5
            }
        }
        const V_B = vNow * multiplierGainB;

        // C. Other Events (Baseline)
        // 1.0% chance of Golden (20x).
        // Gain factor = 20.
        // V_C = vNow * (1 + P_Golden * 20) ???
        // Wait, "V_HarvestNow * (1 + P_Golden * 20)" -> This implies P_Golden is small, 
        // e.g. 0.01. So val = vNow * (1 + 0.2) = 1.2 * vNow?
        // "Calculate the expected baseline gain V_C"
        // Prompt formula: V_C = V_HarvestNow * (1 + P_Golden * 20)
        // Is it additive? Gain = 20x value? Or is specific mutation 20x?
        // If I have 1x multiplier. Get Golden -> 20x. Gain is +19x?
        // Factor = 20.
        // Expected Factor = (1 - P) * 1 + P * 20 = 1 - P + 20P = 1 + 19P.
        // Prompt says "1 + P_Golden * 20". This is approx 1 + 20P. Close enough.
        // Let's use Prompt Formula EXACTLY.
        const V_C = vNow * (1 + BASELINE_GOLDEN_CHANCE * 20); // 1 + 0.01*20 = 1.2

        // Total E
        let P_A = worldEvents.P_Next_Rain_Thunderstorm;
        let P_B = worldEvents.P_Next_Frost;

        // CRITICAL CHECK: If crop matures before the event, we can't get the event benefit
        // worldEvents.Time_Until_Next_Event_Hrs is the wait time. 
        // worldEvents.Time_Remaining_Hrs is how much growth is left.
        // If Wait > Remaining, we mature before event.
        // Note: Speed multiplier is already applied to Calculate tRemNext, but that's what remains AFTER wait.
        // If tRemNext < 0, it means we matured DURING the wait.
        // If we mature during the wait, do we get the event? 
        // The event starts AT the end of the wait. So if we mature BEFORE the end of wait, we miss it.
        const timeToEvent = worldEvents.Time_Until_Next_Event_Hrs; // Real hours
        // Need to check if we mature before this real time passed?
        // Crop matures in Time_Remaining_Hrs (assuming standard speed? or current speed?)
        // If current speed is 1x.
        // If speed is 1.5x (Event Active), Time_Remaining_Hrs is still "hours at 1x"? 
        // Usually Time_Remaining is "real time remaining"? 
        // Let's assume Time_Remaining_Hrs is "Time until maturity in real hours at current speed" provided by caller?
        // Or is it "Mass needed"? 
        // Prompt Check 3.2: "Time Remaining in the next state: T_rem(t+dt) = Time_Remaining_Hrs - Delta_T_eff"
        // Delta_T_eff = Time_Until_Next_Event * Speed.
        // This implies Time_Remaining_Hrs is in "Growth Units" (Hours at 1x speed).

        // If T_rem(t+dt) <= 0, we mature *during* or *before* the event.
        // Since the event triggers *at* t+dt, we are already mature.
        // Thus, we likely miss the specific "Event Mutation" which usually requires growing *during* the event (or the event affecting the plant).
        // If the event is "Rain starts now", and we are already mature, does Rain affect us?
        // Usually mutations happen *while growing*.
        // So if tRemNext <= 0, we set P_A and P_B to 0.

        // Also, from user prompt: "If T_rem(t+dt) <= 0 ... calculation focuses only on expected mutation gains over Delta t"
        // This confirms we exclude the specific Event outcome that happens *at* the transition.

        const deltaTEff = worldEvents.Time_Until_Next_Event_Hrs * (worldEvents.Event_Active ? 1.5 : 1.0);
        const nextStateRem = worldEvents.Time_Remaining_Hrs - deltaTEff;

        if (nextStateRem <= 0) {
            P_A = 0;
            P_B = 0;
            // P_C absorbs the probability? Or do we just lose it?
            // "The expected value of waiting, E, is the sum... for the three possible random event outcomes"
            // If Rain is impossible, does P_Rain become "Nothing"?
            // Yes, prob of Rain event occuring is real, but effect is null.
            // So V_A becomes V_Now? Or just exclude from sum?
            // Since probabilities must sum to 1?
            // Actually, P_Next_Rain is prob of *Event*. The Event happens regardless of our crop.
            // But our *Gain* is 0.
            // So V_A = V_Now. V_B = V_Now.
            // Effectively, we just take the Baseline gain.
        }

        const P_C = 1.0 - P_A - P_B;

        // If we can't benefit from events, V_A and V_B should fallback to V_Now? 
        // Or V_C? 
        // If Event happens (Rain), but we are mature -> No effect -> Value = V_Now.
        const final_V_A = (nextStateRem <= 0) ? vNow : V_A;
        const final_V_B = (nextStateRem <= 0) ? vNow : V_B;
        // Baseline gain applies over Delta t?
        // "1.0% random chance per growth cycle (Delta t)"
        // If we only grow for part of Delta t?
        // Let's assume Baseline applies fully for now, or maybe only if we are growing?
        // If we stop growing halfway, chance is lower. 
        // But let's stick to simple: V_C applies.

        return (P_A * final_V_A) + (P_B * final_V_B) + (P_C * V_C);
    }

    static calculateBloodMoonValue(vNow) {
        // 33% chance of 4x Bloodlit. 
        // Note: Bloodlit is 4x.
        // Formula from prompt: vNow * (1 + 0.33 * 4x)
        // "4x" probably means the number 4.
        return vNow * (1 + 0.33 * 4);
    }
}

// Browser / Node compatibility
if (typeof window !== 'undefined') {
    window.MagicBot = window.MagicBot || {};
    window.MagicBot.Decision = Decision;
}

if (typeof module !== 'undefined') {
    module.exports = Decision;
}
