// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import { Test } from "forge-std/Test.sol";
import { MutualAidPoolV3 } from "../../contracts/mutualaid/MutualAidPoolV3.sol";

contract ReentrantContributionToken {
    MutualAidPoolV3 public pool;
    bool public attempted;
    bool public reentrySucceeded;
    mapping(address => uint256) public balanceOf;

    function setPool(MutualAidPoolV3 pool_) external {
        pool = pool_;
    }

    function mint(address to, uint256 amount) external {
        balanceOf[to] += amount;
    }

    function transferFrom(address from, address to, uint256 amount) external returns (bool) {
        if (!attempted) {
            attempted = true;
            (reentrySucceeded,) = address(pool).call(abi.encodeCall(pool.contributeERC20, (1)));
        }
        balanceOf[from] -= amount;
        balanceOf[to] += amount;
        return true;
    }

    function transfer(address, uint256) external pure returns (bool) {
        return true;
    }
}

contract MutualAidPoolV3Test is Test {
    function test_nativePoolRejectsERC20ContributionPath() external {
        MutualAidPoolV3 pool = new MutualAidPoolV3(address(this), address(0), 1 ether, 10 ether);

        vm.expectRevert(MutualAidPoolV3.TransferFailed.selector);
        pool.contributeERC20(1);

        assertEq(pool.totalContributed(), 0);
    }

    function test_erc20ContributionRejectsTokenCallbackReentrancy() external {
        ReentrantContributionToken token = new ReentrantContributionToken();
        MutualAidPoolV3 pool = new MutualAidPoolV3(address(this), address(token), 1 ether, 10 ether);
        token.setPool(pool);
        token.mint(address(this), 5);

        pool.contributeERC20(5);

        assertTrue(token.attempted());
        assertFalse(token.reentrySucceeded());
        assertEq(pool.totalContributed(), 5);
    }
}
