// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { Kraiken } from "../src/Kraiken.sol";
import { LiquidityManager } from "../src/LiquidityManager.sol";
import { ThreePositionStrategy } from "../src/abstracts/ThreePositionStrategy.sol";
import { IWETH9 } from "../src/interfaces/IWETH9.sol";
import { ConfigurableOptimizer } from "../test/mocks/ConfigurableOptimizer.sol";
import { FuzzingBase } from "./helpers/FuzzingBase.sol";
import "forge-std/Vm.sol";
import "forge-std/console2.sol";

/// @title ScarcityDiagnostic
/// @notice Diagnose when EthScarcity vs EthAbundance fires and why CI has zero effect
/// @dev Tests various scenarios to find conditions where EthAbundance triggers
contract ScarcityDiagnostic is FuzzingBase {
    event EthScarcity(int24 currentTick, uint256 ethBalance, uint256 outstandingSupply, uint256 vwap, int24 vwapTick);
    event EthAbundance(int24 currentTick, uint256 ethBalance, uint256 outstandingSupply, uint256 vwap, int24 vwapTick);

    function run() public {
        _initInfrastructure();

        console2.log("=== Scarcity/Abundance Diagnostic ===");
        console2.log("");

        _testScenario1_InitialRecenter();
        _testScenario2_BullPhase();
        _testScenario3_PostSellRecenter();
        _testScenario4_HighFundingRatio();
    }

    /// Scenario 1: Fresh deployment — no trading. Should be abundance.
    function _testScenario1_InitialRecenter() internal {
        console2.log("--- Scenario 1: Fresh deployment, initial recenter ---");

        ConfigurableOptimizer opt = new ConfigurableOptimizer(5e17, 2e17, 80, 5e17);
        _setupEnvironment(address(opt), true, true);

        // Check state before recenter
        uint256 totalSupply = kraiken.totalSupply();
        uint256 lmBalance = kraiken.balanceOf(address(lm));
        uint256 outstanding = kraiken.outstandingSupply();
        uint256 ethBal = address(lm).balance + weth.balanceOf(address(lm));

        console2.log("  totalSupply:", totalSupply);
        console2.log("  lmBalance:", lmBalance);
        console2.log("  outstandingSupply:", outstanding);
        console2.log("  lm ETH balance:", ethBal);

        // Now do a recenter and look for events
        console2.log("  Doing recenter...");
        vm.recordLogs();
        _tryRecenter();

        _analyzeEvents();

        // Post-recenter state
        outstanding = kraiken.outstandingSupply();
        console2.log("  outstandingSupply after:", outstanding);
        console2.log("");
    }

    /// Scenario 2: After 5 buys (bull phase). Should be scarcity.
    function _testScenario2_BullPhase() internal {
        console2.log("--- Scenario 2: After 5 buys x 15 ETH (bull phase) ---");

        ConfigurableOptimizer opt = new ConfigurableOptimizer(5e17, 2e17, 80, 5e17);
        _setupEnvironment(address(opt), false, true);

        // Fund trader
        vm.deal(trader, 100 ether);
        vm.prank(trader);
        weth.deposit{ value: 100 ether }();

        // Do 5 buys with recenters
        for (uint256 i = 0; i < 5; i++) {
            _executeBuy(15 ether);
            if (i % 2 == 1) _tryRecenter();
        }

        uint256 outstanding = kraiken.outstandingSupply();
        uint256 ethBal = address(lm).balance + weth.balanceOf(address(lm));
        uint256 traderKrk = kraiken.balanceOf(trader);

        console2.log("  outstandingSupply:", outstanding);
        console2.log("  lm ETH balance:", ethBal);
        console2.log("  trader KRK:", traderKrk);

        console2.log("  Doing recenter...");
        vm.recordLogs();
        _tryRecenter();
        _analyzeEvents();
        console2.log("");
    }

    /// Scenario 3: After bull + complete sell. Should be closer to abundance.
    function _testScenario3_PostSellRecenter() internal {
        console2.log("--- Scenario 3: Bull then sell all, recenter ---");

        ConfigurableOptimizer opt = new ConfigurableOptimizer(5e17, 2e17, 80, 5e17);
        _setupEnvironment(address(opt), true, true);

        // Fund trader
        vm.deal(trader, 100 ether);
        vm.prank(trader);
        weth.deposit{ value: 100 ether }();

        // Buy phase
        for (uint256 i = 0; i < 5; i++) {
            _executeBuy(15 ether);
            if (i % 2 == 1) _tryRecenter();
        }
        _tryRecenter();

        // Now sell ALL KRK
        _liquidateTraderHoldings();

        uint256 outstanding = kraiken.outstandingSupply();
        uint256 ethBal = address(lm).balance + weth.balanceOf(address(lm));
        uint256 traderKrk = kraiken.balanceOf(trader);

        console2.log("  outstandingSupply (after sell):", outstanding);
        console2.log("  lm ETH balance:", ethBal);
        console2.log("  trader KRK remaining:", traderKrk);

        console2.log("  Doing recenter after sell...");
        vm.recordLogs();
        _tryRecenter();
        _analyzeEvents();
        console2.log("");
    }

    /// Scenario 4: Very high LM funding relative to trading (should be abundance)
    function _testScenario4_HighFundingRatio() internal {
        console2.log("--- Scenario 4: High LM funding (2000 ETH), tiny buy ---");

        ConfigurableOptimizer opt = new ConfigurableOptimizer(5e17, 2e17, 80, 5e17);
        _setupEnvironment(address(opt), false, true, 2000 ether);

        // Fund trader with small amount
        vm.deal(trader, 5 ether);
        vm.prank(trader);
        weth.deposit{ value: 5 ether }();

        // Tiny buy
        _executeBuy(1 ether);

        uint256 outstanding = kraiken.outstandingSupply();
        uint256 ethBal = address(lm).balance + weth.balanceOf(address(lm));

        console2.log("  outstandingSupply:", outstanding);
        console2.log("  lm ETH balance:", ethBal);

        console2.log("  Doing recenter...");
        vm.recordLogs();
        _tryRecenter();
        _analyzeEvents();
        console2.log("");
    }

    function _analyzeEvents() internal {
        Vm.Log[] memory logs = vm.getRecordedLogs();

        bytes32 scarcitySig = keccak256("EthScarcity(int24,uint256,uint256,uint256,int24)");
        bytes32 abundanceSig = keccak256("EthAbundance(int24,uint256,uint256,uint256,int24)");

        bool foundScarcity = false;
        bool foundAbundance = false;

        for (uint256 i = 0; i < logs.length; i++) {
            if (logs[i].topics.length > 0 && logs[i].topics[0] == scarcitySig) {
                foundScarcity = true;
                (int24 tick, uint256 ethBal, uint256 supply, uint256 vwap, int24 vwapTick) = abi.decode(logs[i].data, (int24, uint256, uint256, uint256, int24));
                console2.log("  >> EthScarcity fired");
                console2.log("     ethBalance:", ethBal);
                console2.log("     outstandingSupply:", supply);
            }
            if (logs[i].topics.length > 0 && logs[i].topics[0] == abundanceSig) {
                foundAbundance = true;
                (int24 tick, uint256 ethBal, uint256 supply, uint256 vwap, int24 vwapTick) = abi.decode(logs[i].data, (int24, uint256, uint256, uint256, int24));
                console2.log("  >> EthAbundance fired");
                console2.log("     ethBalance:", ethBal);
                console2.log("     outstandingSupply:", supply);
            }
        }

        if (!foundScarcity && !foundAbundance) {
            console2.log("  >> No scarcity/abundance event (no VWAP data?)");
        }
    }
}
