// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract TestPresaleContract {
    address payable public owner;
    uint256 public currentStage;
    mapping(uint256 => uint256) public stagePrices;
    mapping(address => uint256) public ethContributions;
    mapping(address => uint256) public tokenBalances;

    event PurchaseWithETH(address indexed buyer, uint256 ethAmount, uint256 tokenAmount);

    constructor() {
        owner = payable(msg.sender);
        initializeStagePrices();
    }

    function initializeStagePrices() internal {
        stagePrices[1] = 700;    // Stage 1: $0.00700 per token
        stagePrices[2] = 770;    // Stage 2: $0.00770 per token
        stagePrices[3] = 850;    // Stage 3: $0.00850 per token
        stagePrices[4] = 930;    // Stage 4: $0.00930 per token
        stagePrices[5] = 1030;   // Stage 5: $0.01030 per token
        stagePrices[6] = 1130;   // Stage 6: $0.01130 per token
        stagePrices[7] = 1240;   // Stage 7: $0.01240 per token
        stagePrices[8] = 1370;   // Stage 8: $0.01370 per token
    }

    function buyWithETH() external payable {
        require(msg.value > 0, "Cannot buy with 0 ETH");
        require(currentStage > 0, "Presale has not started");
        
        uint256 tokenAmount = calculateTokenAmount(msg.value);
        ethContributions[msg.sender] += msg.value;
        tokenBalances[msg.sender] += tokenAmount;

        emit PurchaseWithETH(msg.sender, msg.value, tokenAmount);
        forwardFunds();
    }

    function calculateTokenAmount(uint256 ethAmount) internal view returns (uint256) {
        return ethAmount * stagePrices[currentStage];
    }

    function forwardFunds() internal {
        (bool sent, ) = owner.call{value: msg.value}("");
        require(sent, "Failed to send Ether");
    }

    function setCurrentStage(uint256 stage) external {
        require(msg.sender == owner, "Only owner can set the stage");
        currentStage = stage;
    }

    function withdraw() external {
        require(msg.sender == owner, "Only owner can withdraw");
        (bool sent, ) = owner.call{value: address(this).balance}("");
        require(sent, "Failed to withdraw Ether");
    }
}