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

import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
// Ensure TimelockController is compiled so it can be deployed by name.
import "@openzeppelin/contracts/governance/TimelockController.sol";

/**
 * @title AereGovernor
 * @notice A standard, audit-ready OpenZeppelin Governor for AERE Network.
 *
 *         Unlike the deployed AereGovernanceStaked (which executes via
 *         address(this).call on opaque data, owns nothing, and reads a
 *         deprecated staking contract that reports zero stake), this Governor:
 *           - executes arbitrary (target, value, calldata) batches THROUGH a
 *             TimelockController with an enforced delay (binding, not theatre);
 *           - reads a CHECKPOINTED IVotes source (AereStakedGovVotes) so voting
 *             weight is snapshot-fixed and not flash-stake borrowable;
 *           - counts votes with the standard For / Against / Abstain module,
 *             simple-majority pass rule, and a quorum expressed as a fraction of
 *             the votes token's past total supply.
 *
 *         It is deliberately a plain OZ Governor so it can be externally audited
 *         against a well-known reference before it is ever granted authority
 *         over anything of value.
 */
contract AereGovernor is
    Governor,
    GovernorSettings,
    GovernorCountingSimple,
    GovernorVotes,
    GovernorVotesQuorumFraction,
    GovernorTimelockControl
{
    constructor(
        IVotes votesToken,
        TimelockController timelock,
        uint256 initialVotingDelay, // in blocks
        uint256 initialVotingPeriod, // in blocks
        uint256 initialProposalThreshold, // in votes units
        uint256 quorumPercent // e.g. 10 = 10% of past total supply
    )
        Governor("AereGovernor")
        GovernorSettings(initialVotingDelay, initialVotingPeriod, initialProposalThreshold)
        GovernorVotes(votesToken)
        GovernorVotesQuorumFraction(quorumPercent)
        GovernorTimelockControl(timelock)
    {}

    // ---------------------------------------------------------------------
    // The functions below are pure Solidity multiple-inheritance overrides.
    // ---------------------------------------------------------------------

    function votingDelay() public view override(IGovernor, GovernorSettings) returns (uint256) {
        return super.votingDelay();
    }

    function votingPeriod() public view override(IGovernor, GovernorSettings) returns (uint256) {
        return super.votingPeriod();
    }

    function quorum(uint256 timepoint)
        public
        view
        override(IGovernor, GovernorVotesQuorumFraction)
        returns (uint256)
    {
        return super.quorum(timepoint);
    }

    function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
        return super.proposalThreshold();
    }

    function state(uint256 proposalId)
        public
        view
        override(Governor, GovernorTimelockControl)
        returns (ProposalState)
    {
        return super.state(proposalId);
    }

    function _execute(
        uint256 proposalId,
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) internal override(Governor, GovernorTimelockControl) {
        super._execute(proposalId, targets, values, calldatas, descriptionHash);
    }

    function _cancel(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) internal override(Governor, GovernorTimelockControl) returns (uint256) {
        return super._cancel(targets, values, calldatas, descriptionHash);
    }

    function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) {
        return super._executor();
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(Governor, GovernorTimelockControl)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}
