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

import {Test} from "forge-std/Test.sol";
import {ReserveCommitmentStore} from "../../contracts/hybx-omnl/ReserveCommitmentStore.sol";
import {OMNLJurisdictionPolicyRegistry} from "../../contracts/hybx-omnl/OMNLJurisdictionPolicyRegistry.sol";
import {OMNLNotaryRegistry} from "../../contracts/hybx-omnl/OMNLNotaryRegistry.sol";

contract ReserveNotaryGateTest is Test {
    uint256 internal constant PK = 0xA11CE;

    ReserveCommitmentStore public store;
    OMNLNotaryRegistry public notary;
    bytes32 internal constant LINE = keccak256("LINE");
    bytes32 internal constant JUR = keccak256("ID");
    bytes32 internal constant ROW = keccak256("ID-OMNL-001");
    bytes32 internal constant EV = keccak256("evidence");

    function setUp() public {
        OMNLJurisdictionPolicyRegistry jur = new OMNLJurisdictionPolicyRegistry(address(this));
        notary = new OMNLNotaryRegistry(address(this), address(jur));
        store = new ReserveCommitmentStore(address(this));
        store.configureNotaryGate(address(notary), true, JUR, ROW);
        store.grantRole(store.RESERVE_COMMITTER_ROLE(), address(this));
        notary.setNotarySigner(vm.addr(PK), true);
        notary.setGlobalNotaryThreshold(1);
    }

    function testCommitFailsWithoutNotarization() public {
        vm.expectRevert("ReserveCommitmentStore: evidence not notarized");
        store.commitReserve(LINE, 100, block.timestamp + 1 days, EV, bytes32(0));
    }

    function testCommitSucceedsAfterNotarization() public {
        bytes[] memory sigs = new bytes[](1);
        sigs[0] = _signNotary(0);
        notary.notarizeAttested(JUR, ROW, EV, bytes32(0), bytes32(0), OMNLNotaryRegistry.NotarizationKind.EvidencePackage, 0, sigs);
        store.commitReserve(LINE, 100, block.timestamp + 1 days, EV, bytes32(0));
        assertEq(store.getCommitment(LINE).R, 100);
    }

    function _signNotary(uint256 nonce) internal view returns (bytes memory) {
        bytes32 digest = keccak256(
            abi.encode(
                notary.NOTARIZATION_TYPEHASH(),
                block.chainid,
                address(notary),
                JUR,
                ROW,
                EV,
                bytes32(0),
                bytes32(0),
                nonce
            )
        );
        bytes32 ethSignedMessageHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", digest));
        (uint8 v, bytes32 r, bytes32 s) = vm.sign(PK, ethSignedMessageHash);
        return abi.encodePacked(r, s, v);
    }
}
