// Main Entry Point
console.log("%c Magic Garden Bot Starting... ", "background: #222; color: #bada55; font-size: 20px");

(function () {
    const MB = window.MagicBot;

    // --- AUTOMATION STATE ---
    MB.settings = {
        debug: false
    };

    MB.automation = {
        autoPlant: false,

        autoHarvest: false,
        autoSell: false,
        autoSell: false,
        autoFeed: false,
        smartHarvest: false,
        autoBuyItems: new Set(), // Set of species names to auto-buy
        petDiet: new Set(), // Set of species names allowed for pets
        petDiet: new Set(), // Set of species names allowed for pets
        selectedSeed: null, // The seed user wants to auto-plant
        weatherTracker: {
            lastEndTime: Date.now(), // Assume clear sky starts now if unknown
            currentEvent: null
        }
    };

    function updateWeatherTracker() {
        if (!MB.state || !MB.state.child || !MB.state.child.data) return;

        const currentWeather = MB.state.child.data.weather; // 'Rain', 'Frost', or null
        const tracker = MB.automation.weatherTracker;

        // Detect end of event (Value -> Null)
        if (tracker.currentEvent && !currentWeather) {
            console.log(`[WeatherTracker] Event ${tracker.currentEvent} ended. Timer reset.`);
            tracker.lastEndTime = Date.now();
        }

        // Detect start of event (Null -> Value)
        if (!tracker.currentEvent && currentWeather) {
            console.log(`[WeatherTracker] Event ${currentWeather} started!`);
        }

        tracker.currentEvent = currentWeather;
    }

    // --- AUTOMATION LOOP ---
    setInterval(() => {
        if (!MB.state || !MB.socket) return;

        updateWeatherTracker();

        // Update Weather Stats for UI
        if (MB.automation.weatherTracker) {
            MB.automation.weatherTracker.probabilities = getWorldEvents(MB.state);
        }

        // 1. Auto Harvest
        if (MB.automation.autoHarvest && MB.state.garden && MB.state.garden.tileObjects) {
            const now = Date.now();
            Object.keys(MB.state.garden.tileObjects).forEach(slotId => {
                const tile = MB.state.garden.tileObjects[slotId];
                if (tile && tile.slots) {
                    tile.slots.forEach((s, idx) => {
                        // Debug Logging
                        if (MB.settings && MB.settings.debug) {
                            console.log(`[AutoHarvest] Checking Slot ${slotId} Index ${idx}:`, {
                                species: s.species,
                                ready: now >= s.endTime,
                                timeLeft: (s.endTime - now) / 1000,
                                mutations: s.mutations
                            });
                        }

                        if (now >= s.endTime) {
                            const mutations = s.mutations || [];

                            // Smart Harvest Logic
                            if (MB.automation.smartHarvest) {
                                // 0. Safety: Check for Planted Eggs
                                // Eggs usually have objectType 'egg' or similar. 
                                // Based on standard state structures, if checks fail, better safe than sorry.
                                // Inspecting fullstate shows objectType property on the tile itself.
                                if (tile.objectType && tile.objectType.toLowerCase().includes('egg')) {
                                    if (MB.settings && MB.settings.debug) console.log(`[AutoHarvest] Skipping Egg at slot ${slotId}`);
                                    return;
                                }

                                const isRainbow = mutations.includes('Rainbow');
                                const isGold = mutations.includes('Gold');
                                const isFrozen = mutations.includes('Frozen');
                                const isWet = mutations.includes('Wet');
                                const duration = s.endTime - s.startTime; // Duration in ms

                                // 1. Rainbow Strategy: Harvest Priority (x50)
                                // Rainbow doesn't stack well and is huge value. Cash out.
                                if (isRainbow) {
                                    // Harvest immediately!
                                    // Fall through to harvest call.
                                    if (MB.settings && MB.settings.debug) console.log(`[AutoHarvest] Harvesting Rainbow at ${slotId}`);
                                }
                                // 2. Gold Strategy: Wait for Frozen (x200 EV)
                                else if (isGold && !isFrozen) {
                                    if (MB.settings && MB.settings.debug) console.log(`[AutoHarvest] Skipping Gold (Waiting for Frozen) at ${slotId}`);
                                    return; // Skip
                                }
                                // 3. Long Crop Strategy (> 10 mins): Wait for Wet (x2 EV)
                                // Continues to Bellman Logic below...

                                // 4. Bellman Step (Section 3) Smart Harvest
                                // Check if decision module is loaded
                                if (MB.Decision) {
                                    const worldEvents = getWorldEvents(MB.state);
                                    const cropState = {
                                        species: s.species || tile.species,
                                        baseValue: s.baseValue || 1, // Need base value source?
                                        scale: s.scale || 1, // Can use targetScale or derive current scale?
                                        mutations: mutations
                                    };

                                    const events = {
                                        ...worldEvents,
                                        Time_Remaining_Hrs: (s.endTime - Date.now()) / 3600000
                                    };
                                    const logic = MB.Decision.shouldHarvest(cropState, events);

                                    if (MB.settings && MB.settings.debug) {
                                        console.log(`[SmartHarvest] Slot ${slotId}: ${logic.action}`, logic);
                                    }

                                    if (logic.action === 'WAIT') {
                                        return; // Skip harvest
                                    }
                                }
                            }

                            // Don't spam: check if we just sent it? 
                            // For simplicity, relying on server or next state update. 
                            // A simple dedupe could be added if needed.
                            MB.sendMsg({
                                type: 'HarvestCrop',
                                slot: parseInt(slotId),
                                slotsIndex: idx,
                                scopePath: ["Room", "Quinoa"]
                            });
                            if (MB.settings && MB.settings.debug) console.log(`[AutoHarvest] Sent HarvestCrop for ${slotId}`);
                        }
                    });
                }
            });
        }

        // 2. Auto Plant
        if (MB.automation.autoPlant && MB.state.garden && MB.state.garden.tileObjects) {
            // Find a seed to plant
            let seedToPlant = MB.automation.selectedSeed;

            // Fallback: If no selected seed, find FIRST available seed in inventory
            if (!seedToPlant && MB.state.inventory && MB.state.inventory.items) {
                const firstSeed = MB.state.inventory.items.find(i => i.itemType === 'Seed' && (i.quantity > 0 || i.count > 0));

                if (firstSeed) {
                    // Extract species name similar to ui.js logic
                    if (firstSeed.species) seedToPlant = firstSeed.species;
                    else if (firstSeed.parameters && firstSeed.parameters.species) seedToPlant = firstSeed.parameters.species;
                    else if (firstSeed.parameters && firstSeed.parameters.speciesIds) {
                        const vals = Object.values(firstSeed.parameters.speciesIds);
                        if (vals.length > 0) seedToPlant = vals[0];
                    }
                }
            }

            if (seedToPlant) {
                // Find empty slot
                // We'll plant ONE seed per tick to avoid flooding and ensuring state sync
                let emptySlot = -1;
                for (let i = 0; i < 200; i++) {
                    const slotId = i.toString();
                    const tile = MB.state.garden.tileObjects[slotId];
                    const hasCrop = tile && tile.slots && tile.slots.length > 0;
                    if (!hasCrop) {
                        emptySlot = i;
                        break;
                    }
                }

                if (emptySlot !== -1) {
                    MB.sendMsg({
                        type: "PlantSeed",
                        slot: emptySlot,
                        species: seedToPlant,
                        scopePath: ["Room", "Quinoa"]
                    });
                }
            }
        }

        // 3. Auto Sell
        if (MB.automation.autoSell) {
            // Check if we have any produce? For now, just trigger SellAll periodically.
            // Just trigger it every loop? Might be too much.
            // Let's check inventory for "Produce"
            if (MB.state.inventory && MB.state.inventory.items) {
                const hasProduce = MB.state.inventory.items.some(i => i.itemType === 'Produce');
                if (hasProduce) {
                    MB.sellAll();
                }
            }
        }

        // 4. Auto Buy
        if (MB.automation.autoBuyItems.size > 0 && MB.state.shops && MB.state.shops.seed) {
            MB.state.shops.seed.inventory.forEach(item => {
                if (MB.automation.autoBuyItems.has(item.species)) {
                    // Check stock
                    let purchased = 0;
                    if (MB.state.shopPurchases && MB.state.shopPurchases.seed && MB.state.shopPurchases.seed.purchases) {
                        purchased = MB.state.shopPurchases.seed.purchases[item.species] || 0;
                    }
                    const currentStock = Math.max(0, item.initialStock - purchased);

                    if (currentStock > 0) {
                        // Buy ONE
                        MB.sendMsg({
                            scopePath: ["Room", "Quinoa"],
                            type: "PurchaseSeed",
                            species: item.species
                        });
                        console.log(`[MagicBot] Auto-buying ${item.species}`);
                    }
                }
            });
        }

    }, 1000); // Run every 1 second

    // --- HELPER FUNCTIONS ---

    MB.feedPets = function () {
        if (!MB.state.inventory || !MB.state.inventory.items) return;

        const inventory = MB.state.inventory.items;
        const pets = inventory.filter(i => i.itemType === 'Pet');

        if (pets.length === 0) return;

        // Group food by species for easy lookup
        const foodMap = {};
        inventory.forEach(i => {
            if (i.itemType === 'Produce' || i.itemType === 'Seed' || i.itemType === 'Plant') { // Assuming crops are Produce, but could be Plant? Wiki says "crops". Usually 'Produce' in inventory.
                // Double check itemType for crops in inventory. 
                // In fullstate.json, crops aren't explicitly shown in inventory in the snippet, but seeds are.
                // Assuming harvested crops are 'Produce'.
                // We will check matches against petDiet.
                let species = i.species;
                // Fallback for complex objects
                if (!species && i.parameters && i.parameters.species) species = i.parameters.species;

                if (species && (i.quantity > 0 || i.count > 0)) {
                    if (!foodMap[species]) foodMap[species] = [];
                    foodMap[species].push(i);
                }
            }
        });

        pets.forEach(pet => {
            // Check hunger?
            // "hunger": 405.555...  This likely means current fullness or hunger? 
            // Wiki says "restores hunger". 
            // If it's 0-100 scale, 405 is odd. Maybe it's max hunger?
            // Or maybe it's "hunger points" where higher = more hungry? 
            // Or higher = more full?
            // Let's assume we feed if we can. The server will reject if full.

            if (MB.automation.petDiet.size === 0) return;

            // Find valid food
            for (const allowedSpecies of MB.automation.petDiet) {
                if (foodMap[allowedSpecies]) {
                    const foodItems = foodMap[allowedSpecies];
                    // Use the first available stack
                    const foodItem = foodItems[0];

                    if (foodItem) {
                        // Send Feed Command
                        // We need the proper message structure.
                        // User request: {"scopePath":["Room","Quinoa"],"type":"FeedPet","petItemId":"...","cropItemId":"..."}

                        console.log(`[MagicBot] Feeding ${pet.petSpecies} with ${allowedSpecies}`);

                        MB.sendMsg({
                            scopePath: ["Room", "Quinoa"], // value from user request, should be dynamic? but hardcoded in other places in this file. "Quinoa" seems to be the game instance. 
                            type: "FeedPet",
                            petItemId: pet.id,
                            cropItemId: foodItem.id
                        });

                        // Optimistically decrement count to prevent double usage in same tick (if we loop)? 
                        // But we are sending async. 
                        // Just one food per pet per tick is safer to avoid spam.
                        break;
                    }
                }
            }
        });
    };

    // Override sellAll to chain feeding
    const originalSellAll = MB.sellAll || (() => { });
    MB.sellAll = function () {
        if (MB.automation.autoFeed) {
            MB.feedPets();
            // Small delay? Or just send immediately after?
            // WebSocket is ordered.
        }

        // originalSellAll implementation wasn't defined in the file view I saw, 
        // but 'MB.sellAll()' was called in line 131. 
        // It must be defined somewhere or attached to MB. 
        // Wait, line 85 of browser_cheats.js defines window.sell. 
        // line 184 of ui.js calls MB.sellAll(). 
        // I don't see MB.sellAll defined in core.js or main.js PROPERLY.
        // Let's look at ui.js again. 
        // ui.js calls `MB.sellAll()`. 
        // check `browser_cheats.js` - it defines `window.sell`.
        // `main.js` calls `MB.sellAll()`.

        // Detailed check:
        // core.js defines MB = {...}.
        // main.js uses MB.
        // ui.js uses MB.
        // I suspect MB.sellAll is NOT defined yet or I missed it in `main.js` or `core.js` or `ui.js`.
        // Ah, `ui.js` line 184 calls it. 
        // `main.js` line 131 calls it.
        // If it's not defined, it will crash. 
        // Let's define it if missing.

        if (!MB.state.socket && window.gameSocket) {
            // Fallback to browser cheats style if needed
        }

        MB.sendMsg({
            type: 'SellAllCrops',
            scopePath: ["Room", "Quinoa"]
        });
        console.log("[MagicBot] Selling all crops");
        console.log("[MagicBot] Selling all crops");
    };

    function getWorldEvents(state) {
        const defaults = {
            Time_Until_Next_Event_Hrs: 0.5, // Fallback
            P_Next_Rain_Thunderstorm: 0.0,
            P_Next_Frost: 0.0,
            Time_To_Next_Blood_Moon_Hrs: 999, // Unknown for now
            Event_Active: false
        };

        if (!state || !MB.automation.weatherTracker) return defaults;

        const tracker = MB.automation.weatherTracker;
        const currentWeather = tracker.currentEvent;

        // Logic: 20-35 mins interval (Avg 27.5m)
        // Rain 75%, Frost 25%

        const AVG_INTERVAL_MS = 27.5 * 60 * 1000;

        let timeUntilNextHrs = 0;
        let pRain = 0;
        let pFrost = 0;
        let active = false;

        if (currentWeather) {
            // Event is ACTIVE
            active = true;
            // If active, we are IN the weather.
            // Probabilities for "Next Event types" are effectively 1.0 for the current type for short-term planning?
            if (currentWeather.includes('Rain') || currentWeather.includes('Thunder')) {
                pRain = 1.0;
            } else if (currentWeather.includes('Frost') || currentWeather.includes('Snow')) {
                pFrost = 1.0;
            }
            // Planning Horizon: 5 mins (0.083 hrs) to accumulate mutation checks
            timeUntilNextHrs = 0.083;
        } else {
            // Clear Sky - Waiting for Next Event
            const nextEventTime = tracker.lastEndTime + AVG_INTERVAL_MS;
            const diffMs = nextEventTime - Date.now();
            timeUntilNextHrs = Math.max(0, diffMs) / 3600000; // Hours

            // If we heavily overdue (e.g. > 35 mins), probability increases? 
            // For V1, fixed probs:
            pRain = 0.75;
            pFrost = 0.25;
        }

        return {
            Time_Until_Next_Event_Hrs: timeUntilNextHrs,
            P_Next_Rain_Thunderstorm: pRain,
            P_Next_Frost: pFrost,
            Time_To_Next_Blood_Moon_Hrs: 999,
            Event_Active: active
        };
    }

})();
