#include <Block/SpriteBlock/BasicBlock/LogBlock/LogBlock.hpp>
#include <BlockRegistry/BlockRegistry.hpp>
#include <Milestone/BrickByBrickMilestone/BrickByBrickMilestone.hpp>
#include <Milestone/DiggingDeeperMilestone/DiggingDeeperMilestone.hpp>
#include <Milestone/DripMilestone/DripMilestone.hpp>
#include <Milestone/ElectronicsMilestone/ElectronicsMilestone.hpp>
#include <Milestone/FossilFuelsMilestone/FossilFuelsMilestone.hpp>
#include <Milestone/HydraulicsMilestone/HydraulicsMilestone.hpp>
#include <Milestone/IndustrialRevolutionMilestone/IndustrialRevolutionMilestone.hpp>
#include <Milestone/MetalWorkingMilestone/MetalWorkingMilestone.hpp>
#include <Milestone/NavigationMilestone/NavigationMilestone.hpp>
#include <PlayerTriggerRegistry/PlayerTriggerRegistry.hpp>
#include <Milestone/StoneAgeMilestone/StoneAgeMilestone.hpp>
#include <Milestone/CarpentryMilestone/CarpentryMilestone.hpp>
#include <Milestone/BronzeAgeMilestone/BronzeAgeMilestone.hpp>
#include <Utilities/Utilities.hpp>

PlayerTriggerRegistry playerTriggerRegistry;

void PlayerTriggerRegistry::when(std::string trigger, std::string milestoneId, int achievementId)
{
    triggerMap[trigger] = std::pair(milestoneId, achievementId);
}

void PlayerTriggerRegistry::whenItemCollected(std::string name, std::string milestoneId, int achievementId)
{
    when(formatString("main:ItemCollected::$+", name), milestoneId, achievementId);
}

void PlayerTriggerRegistry::whenBlockCollected(std::string name, std::string milestoneId, int achievementId)
{
    when(formatString("main:BlockCollected::$+", name), milestoneId, achievementId);
}

void PlayerTriggerRegistry::whenItemEquipped(std::string name, std::string milestoneId, int achievementId)
{
    when(formatString("main:ItemEquipped::$+", name), milestoneId, achievementId);
}

void PlayerTriggerRegistry::whenItemMoved(std::string name, std::string milestoneId, int achievementId)
{
    when(formatString("main:ItemMoved::$+", name), milestoneId, achievementId);
}

void PlayerTriggerRegistry::whenBlockMoved(std::string name, std::string milestoneId, int achievementId)
{
    when(formatString("main:BlockMoved::$+", name), milestoneId, achievementId);
}

void PlayerTriggerRegistry::whenFluidCollected(std::string name, std::string milestoneId, int achievementId)
{
    when(formatString("main:FluidCollected::$+", name), milestoneId, achievementId);
}

void PlayerTriggerRegistry::whenBlockPlaced(std::string name, std::string milestoneId, int achievementId)
{
    when(formatString("main:BlockPlaced::$+", name), milestoneId, achievementId);
}

void PlayerTriggerRegistry::registerAllTriggers()
{
    // === ITEM COLLECTION ===
    whenItemCollected("main:stick", StoneAgeMilestone::ID, StoneAgeMilestone::CollectStick);

    // === BLOCK COLLECTION ===
    whenBlockCollected("main:pebble", StoneAgeMilestone::ID, StoneAgeMilestone::CollectPebble);
    whenBlockCollected("main:stone", StoneAgeMilestone::ID, StoneAgeMilestone::CollectStone);
    whenBlockCollected("main:clay", BrickByBrickMilestone::ID, BrickByBrickMilestone::CollectClay);
    whenBlockCollected("main:sand", BrickByBrickMilestone::ID, BrickByBrickMilestone::CollectSand);
    whenBlockCollected("main:cactusLog", CarpentryMilestone::ID, CarpentryMilestone::Cactus);

    // === LOG COLLECTION ===
    blockRegistry.forEachBlock([this](Block &block)
    {
        if (isInstance<LogBlock>(block) && block.name != "main:cactusLog")
        {
            whenBlockCollected(block.name, CarpentryMilestone::ID, CarpentryMilestone::CollectWood);
        }
    });

    // === MUSHROOM COLLECTION ===
    blockRegistry.forEachBlock([this](Block &block)
    {
        if (block.isSuffixed("Mushroom"))
        {
            whenBlockCollected(block.name, DripMilestone::ID, DripMilestone::CollectMushroom);
        }
    });

    // === ITEM EQUIPPING ===
    whenItemEquipped("main:carvedMap", NavigationMilestone::ID, NavigationMilestone::CarvedMap);
    whenItemEquipped("main:paperMap", NavigationMilestone::ID, NavigationMilestone::PaperMap);
    whenItemEquipped("main:runningShoes", DripMilestone::ID, DripMilestone::RunningShoes);
    whenItemEquipped("main:backpack", DripMilestone::ID, DripMilestone::Backpack);

    // === ITEM MOVING ===
    whenItemMoved("main:tinIngot", BronzeAgeMilestone::ID, BronzeAgeMilestone::MineTin);
    whenItemMoved("main:copperIngot", BronzeAgeMilestone::ID, BronzeAgeMilestone::MineCopper);
    whenItemMoved("main:brassIngot", BronzeAgeMilestone::ID, BronzeAgeMilestone::MakeBrass);
    whenItemMoved("main:bronzeIngot", BronzeAgeMilestone::ID, BronzeAgeMilestone::MakeBronze);
    whenItemMoved("main:ironIngot", MetalWorkingMilestone::ID, MetalWorkingMilestone::MineIron);
    whenItemMoved("main:nickelIngot", MetalWorkingMilestone::ID, MetalWorkingMilestone::MineNickel);
    whenItemMoved("main:coal", MetalWorkingMilestone::ID, MetalWorkingMilestone::MineCoal);
    whenItemMoved("main:steelIngot", MetalWorkingMilestone::ID, MetalWorkingMilestone::MakeSteel);
    whenItemMoved("main:silverIngot", MetalWorkingMilestone::ID, MetalWorkingMilestone::MineSilver);
    whenItemMoved("main:leadIngot", MetalWorkingMilestone::ID, MetalWorkingMilestone::MineLead);
    whenItemMoved("main:goldIngot", MetalWorkingMilestone::ID, MetalWorkingMilestone::MineGold);
    whenItemMoved("main:siliconIngot", MetalWorkingMilestone::ID, MetalWorkingMilestone::MineSilicon);
    whenItemMoved("main:siliconSheet", MetalWorkingMilestone::ID, MetalWorkingMilestone::MakeSiliconSheet);
    whenItemMoved("main:stoneAxe", CarpentryMilestone::ID, CarpentryMilestone::StoneAxe);
    whenItemMoved("main:bronzeAxe", CarpentryMilestone::ID, CarpentryMilestone::BronzeAxe);
    whenItemMoved("main:ironAxe", CarpentryMilestone::ID, CarpentryMilestone::IronAxe);
    whenItemMoved("main:steelAxe", CarpentryMilestone::ID, CarpentryMilestone::SteelAxe);
    whenItemMoved("main:diamondAxe", CarpentryMilestone::ID, CarpentryMilestone::DiamondAxe);
    whenItemMoved("main:diamondPickaxe", DiggingDeeperMilestone::ID, DiggingDeeperMilestone::DiamondPickaxe);
    whenItemMoved("main:woodPulp", CarpentryMilestone::ID, CarpentryMilestone::MakeWoodPulp);
    whenItemMoved("main:charcoal", CarpentryMilestone::ID, CarpentryMilestone::Charcoal);
    whenItemMoved("main:paperSheet", CarpentryMilestone::ID, CarpentryMilestone::MakePaper);
    whenItemMoved("main:compass", NavigationMilestone::ID, NavigationMilestone::Compass);
    whenItemMoved("main:greenDye", BrickByBrickMilestone::ID, BrickByBrickMilestone::MakeGreenDye);
    whenItemMoved("main:mushroomLeather", DripMilestone::ID, DripMilestone::MakeMushroomLeather);
    whenItemMoved("main:rubberTreeSap", BrickByBrickMilestone::ID, BrickByBrickMilestone::MakeRubberTreeSap);
    whenItemMoved("main:rubber", BrickByBrickMilestone::ID, BrickByBrickMilestone::MakeRubber);
    whenItemMoved("main:jetpack", DripMilestone::ID, DripMilestone::ConstructJetpack);
    whenItemMoved("main:diamond", DiggingDeeperMilestone::ID, DiggingDeeperMilestone::MineDiamonds);
    whenItemMoved("main:electricDrill", DiggingDeeperMilestone::ID, DiggingDeeperMilestone::ElectricDrill);
    whenItemMoved("main:steelClaws", IndustrialRevolutionMilestone::ID, IndustrialRevolutionMilestone::MakeSteelClaws);

    // === BLOCK MOVING ===
    whenBlockMoved("main:glass", BrickByBrickMilestone::ID, BrickByBrickMilestone::MakeGlass);
    whenBlockMoved("main:steelCasing", ElectronicsMilestone::ID, ElectronicsMilestone::MakeSteelCasing);
    whenBlockMoved("main:macerator", ElectronicsMilestone::ID, ElectronicsMilestone::MakeMacerator);
    whenBlockMoved("main:electricFurnace", ElectronicsMilestone::ID, ElectronicsMilestone::MakeElectricFurnace);
    whenBlockMoved("main:solarPanel", ElectronicsMilestone::ID, ElectronicsMilestone::MakeSolarPanel);
    whenBlockMoved("main:dynamo", ElectronicsMilestone::ID, ElectronicsMilestone::MakeDynamo);
    whenBlockMoved("main:accumulator", ElectronicsMilestone::ID, ElectronicsMilestone::MakeAccumulator);
    whenBlockMoved("main:conveyorBelt", IndustrialRevolutionMilestone::ID, IndustrialRevolutionMilestone::MakeConveyorBelt);
    whenBlockMoved("main:beltMotor", IndustrialRevolutionMilestone::ID, IndustrialRevolutionMilestone::MakeBeltMotor);
    whenBlockMoved("main:steelBarrel", HydraulicsMilestone::ID, HydraulicsMilestone::MakeSteelBarrel);
    whenBlockMoved("main:leadBarrel", HydraulicsMilestone::ID, HydraulicsMilestone::MakeLeadBarrel);
    whenBlockMoved("main:itemExtractor", IndustrialRevolutionMilestone::ID, IndustrialRevolutionMilestone::MakeItemExtractor);

    // === FLUID COLLECTION ===
    whenFluidCollected("main:water", HydraulicsMilestone::ID, HydraulicsMilestone::CollectWater);
    whenFluidCollected("main:oil", FossilFuelsMilestone::ID, FossilFuelsMilestone::CollectOil);

    // === BLOCK PLACINNG ===
    whenBlockPlaced("main:chemicalReactor", ElectronicsMilestone::ID, ElectronicsMilestone::BuildChemicalReactor);
    whenBlockPlaced("main:macerator", ElectronicsMilestone::ID, ElectronicsMilestone::BuildMacerator);
    whenBlockPlaced("main:electricFurnace", ElectronicsMilestone::ID, ElectronicsMilestone::BuildElectricFurnace);
    whenBlockPlaced("main:itemExtractor", IndustrialRevolutionMilestone::ID, IndustrialRevolutionMilestone::AttachItemExtractor);
}

void PlayerTriggerRegistry::raise(Player &player, std::string trigger)
{
    auto it = triggerMap.find(trigger);
    if (it == triggerMap.end())
    {
        return;
    }

    auto [milestoneId, achievementId] = it->second;
    player.achieve(milestoneId, achievementId);
}