// File: contracts/HouseMoneyRev.sol



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

contract HouseMoneyRevShareContract3 {
    uint256 public immutable HOUSE_REVENUE_AMOUNT;
    address public owner;
    uint256 public totalSnapshotTokens;
    uint256 public snapshotTime;
    bool public isSnapshotLocked;
    bool public isFreezed;

    mapping(address => uint256) public snapshotBalances;
    mapping(address => bool) public hasClaimed;

    event HouseMoneySnapshotLock();
    event Freeze();
    event EthClaim(address indexed claimer, uint256 amount);
    event AdminWithdraw(uint256 amount);

    constructor() payable {
        owner = msg.sender;
        HOUSE_REVENUE_AMOUNT = msg.value;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Caller is not the owner");
        _;
    }
    //
    modifier after3Days() {
        require(
            block.timestamp > snapshotTime + 3 days,
            "Can withdraw unclaimed ETH after 3 days"
        );
        _;
    }

    function uploadSnapshot(
        address[] calldata users,
        uint256[] calldata balances
    ) external onlyOwner {
        require(
            users.length == balances.length,
            "Addresses and balances length must be equal"
        );
        // require(users.length <= 125, "Can only upload up to 125 addresses at a time");

        // note: should not have more than one user value
        for (uint256 i = 0; i < users.length; i++) {
            snapshotBalances[users[i]] += balances[i];
            totalSnapshotTokens += balances[i];
        }
    }

    function lockSnapshot() external onlyOwner {
        require(!isSnapshotLocked, "snapshot already locked");

        snapshotTime = block.timestamp;
        isSnapshotLocked = true;

        emit HouseMoneySnapshotLock();
    }

    function freeze() external onlyOwner {
        require(!isFreezed, "Contract is already frozen");

        isFreezed = true;

        emit Freeze();
    }

    function claimETH() external {
        require(!isFreezed, "Contract is frozen");
        require(isSnapshotLocked, "Snapshot not yet locked");
        require(!hasClaimed[msg.sender], "You have already claimed your ETH");
        require(
            snapshotBalances[msg.sender] > 0,
            "You're not eligible to claim with 0 House"
        );

        uint256 claimableAmount = (HOUSE_REVENUE_AMOUNT *
            snapshotBalances[msg.sender]) / totalSnapshotTokens;

        // prevent reentrancy
        hasClaimed[msg.sender] = true;

        // see https://ethereum.stackexchange.com/questions/78124/is-transfer-still-safe-after-the-istanbul-update
        (bool isSuccess, ) = msg.sender.call{value: claimableAmount}("");
        require(isSuccess, "Claim amount tranfer failed");

        emit EthClaim(msg.sender, claimableAmount);
    }

    // Function to withdraw unclaimed ETH after 7 days
    function withdrawUnclaimedETH() public onlyOwner after3Days {
        uint256 amount = address(this).balance;
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Withdraw failed");
        emit AdminWithdraw(amount);
    }

    receive() external payable {}
}