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

import {CheckpointExtensionBase} from "./CheckpointExtensionBase.sol";
import {CheckpointStorage} from "../storage/CheckpointStorage.sol";
import {CheckpointEIP712} from "../libraries/CheckpointEIP712.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

/// @notice Validator registry + ECDSA recovery for batch attestations and 65-byte sig bundles.
contract ValidatorSigVerifierExtension is CheckpointExtensionBase {
    using ECDSA for bytes32;

    mapping(address => bool) public validators;
    uint256 public threshold;
    address public verifyingContract;

    event ValidatorSetUpdated(address[] validators, uint256 threshold);

    function HOOK_BEFORE_SUBMIT() external pure override returns (uint32) {
        return 1 << 0;
    }

    function HOOK_AFTER_SUBMIT() external pure override returns (uint32) {
        return 0;
    }

    function HOOK_ON_CCIP() external pure override returns (uint32) {
        return 0;
    }

    function setVerifyingContract(address hub) external {
        verifyingContract = hub;
    }

    function setValidators(address[] calldata addrs, uint256 newThreshold) external {
        for (uint256 i = 0; i < addrs.length; i++) {
            validators[addrs[i]] = true;
        }
        threshold = newThreshold;
        emit ValidatorSetUpdated(addrs, newThreshold);
    }

    function beforeSubmit(CheckpointStorage.CheckpointHeader calldata header, bytes calldata validatorSignatures)
        external
        view
    {
        if (threshold == 0) return;
        require(verifyingContract != address(0), "verifier unset");
        bytes32 digest = CheckpointEIP712.digest(verifyingContract, block.chainid, header);
        if (validatorSignatures.length == 65) {
            address signer = ECDSA.recover(digest, validatorSignatures);
            require(validators[signer], "attest signer");
            return;
        }
        require(validatorSignatures.length >= threshold * 65, "sig length");
        uint256 valid;
        for (uint256 i = 0; i + 65 <= validatorSignatures.length; i += 65) {
            bytes memory sig = new bytes(65);
            for (uint256 j = 0; j < 65; j++) {
                sig[j] = validatorSignatures[i + j];
            }
            address signer = ECDSA.recover(digest, sig);
            if (validators[signer]) valid++;
        }
        require(valid >= threshold, "threshold");
    }

    function afterSubmit(CheckpointStorage.CheckpointHeader calldata, bytes calldata) external pure override {}

    function onCCIPReceive(bytes calldata) external pure override {}
}
