// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {Test} from "forge-std/Test.sol";
import {GovernorVotesSuperQuorumFractionMock} from "../../../contracts/mocks/governance/GovernorVotesSuperQuorumFractionMock.sol";
import {GovernorVotesQuorumFraction} from "../../../contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
import {GovernorVotesSuperQuorumFraction} from "../../../contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol";
import {GovernorSettings} from "../../../contracts/governance/extensions/GovernorSettings.sol";
import {GovernorVotes} from "../../../contracts/governance/extensions/GovernorVotes.sol";
import {Governor} from "../../../contracts/governance/Governor.sol";
import {IVotes} from "../../../contracts/governance/utils/IVotes.sol";
import {ERC20VotesExtendedTimestampMock} from "../../../contracts/mocks/token/ERC20VotesAdditionalCheckpointsMock.sol";
import {EIP712} from "../../../contracts/utils/cryptography/EIP712.sol";
import {ERC20} from "../../../contracts/token/ERC20/ERC20.sol";

contract TokenMock is ERC20VotesExtendedTimestampMock {
    constructor() ERC20("Mock Token", "MTK") EIP712("Mock Token", "1") {}
}

/**
 * Main responsibility: expose the functions that are relevant to the simulation
 */
contract GovernorHandler is GovernorVotesSuperQuorumFractionMock {
    constructor(
        string memory name_,
        uint48 votingDelay_,
        uint32 votingPeriod_,
        uint256 proposalThreshold_,
        IVotes token_,
        uint256 quorumNumerator_,
        uint256 superQuorumNumerator_
    )
        Governor(name_)
        GovernorSettings(votingDelay_, votingPeriod_, proposalThreshold_)
        GovernorVotes(token_)
        GovernorVotesQuorumFraction(quorumNumerator_)
        GovernorVotesSuperQuorumFraction(superQuorumNumerator_)
    {}

    // solhint-disable-next-line func-name-mixedcase
    function $_updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) public {
        _updateSuperQuorumNumerator(newSuperQuorumNumerator);
    }

    // solhint-disable-next-line func-name-mixedcase
    function $_updateQuorumNumerator(uint256 newQuorumNumerator) public {
        _updateQuorumNumerator(newQuorumNumerator);
    }
}

contract GovernorSuperQuorumGreaterThanQuorum is Test {
    GovernorHandler private _governorHandler;

    function setUp() external {
        _governorHandler = new GovernorHandler(
            "GovernorName",
            0, // votingDelay
            1e4, // votingPeriod
            0, // proposalThreshold
            new TokenMock(), // token
            10, // quorumNumerator
            50 // superQuorumNumerator
        );

        // limit the fuzzer scope
        bytes4[] memory selectors = new bytes4[](2);
        selectors[0] = GovernorHandler.$_updateSuperQuorumNumerator.selector;
        selectors[1] = GovernorHandler.$_updateQuorumNumerator.selector;

        targetContract(address(_governorHandler));
        targetSelector(FuzzSelector(address(_governorHandler), selectors));
    }

    // solhint-disable-next-line func-name-mixedcase
    function invariant_superQuorumGreaterThanQuorum() external view {
        assertGe(_governorHandler.superQuorumNumerator(), _governorHandler.quorumNumerator());
    }
}
