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

import { Test } from "forge-std/Test.sol";
import { ERC8004IdentityAdapterV3 } from "../../contracts/identity/ERC8004IdentityAdapterV3.sol";
import { CanonicalIdentityRegistryV3 } from "../../contracts/identity/CanonicalIdentityRegistryV3.sol";
import { IERC8004IdentityRegistry } from "../../contracts/identity/IERC8004IdentityRegistry.sol";

contract IdentityRegistryV3Mock is IERC8004IdentityRegistry {
    bytes32 public constant IDENTITY_SEMANTICS =
        keccak256("Vaultfire.BaseV3.SelfAuthenticatedIdentity.NoBehavioralInputs.v1");

    function getAgent(uint256 agentId) external pure returns (Agent memory) {
        return Agent(agentId, address(1), address(2), address(3), address(4), 1, true);
    }

    function isAuthorizedOperator(uint256, address) external pure returns (bool) {
        return true;
    }

    function isActive(uint256) external pure returns (bool) {
        return true;
    }
}

contract IncompleteIdentityRegistryV3Mock {
    function isAuthorizedOperator(uint256, address) external pure returns (bool) {
        return false;
    }

    function isActive(uint256) external pure returns (bool) {
        return false;
    }
}

contract ERC8004IdentityAdapterV3Test is Test {
    function test_registryIsCodehashPinnedAndRotationIsDisabled() external {
        CanonicalIdentityRegistryV3 registry = new CanonicalIdentityRegistryV3();
        uint256 agentId = 1;
        registry.register(agentId, address(1), address(3), address(4));
        ERC8004IdentityAdapterV3 adapter =
            new ERC8004IdentityAdapterV3(address(this), address(registry), address(registry).codehash);
        assertEq(adapter.registryCodehash(), address(registry).codehash);
        adapter.requireActive(agentId);

        vm.expectRevert(ERC8004IdentityAdapterV3.RegistryPinned.selector);
        adapter.setRegistry(address(registry));
    }

    function test_rejectsEOAAndWrongCodehashTrustRoots() external {
        vm.expectRevert(ERC8004IdentityAdapterV3.InvalidRegistry.selector);
        new ERC8004IdentityAdapterV3(address(this), address(0xBEEF), bytes32(uint256(1)));

        IdentityRegistryV3Mock registry = new IdentityRegistryV3Mock();
        vm.expectRevert(ERC8004IdentityAdapterV3.InvalidRegistry.selector);
        new ERC8004IdentityAdapterV3(address(this), address(registry), bytes32(uint256(1)));

        IncompleteIdentityRegistryV3Mock incomplete = new IncompleteIdentityRegistryV3Mock();
        vm.expectRevert(ERC8004IdentityAdapterV3.InvalidRegistry.selector);
        new ERC8004IdentityAdapterV3(address(this), address(incomplete), address(incomplete).codehash);
    }

    function test_rejectsSchemaCompatibleMaliciousRegistryEvenWithCallerSuppliedMatchingHash() external {
        IdentityRegistryV3Mock malicious = new IdentityRegistryV3Mock();
        vm.expectRevert(ERC8004IdentityAdapterV3.InvalidRegistry.selector);
        new ERC8004IdentityAdapterV3(address(this), address(malicious), address(malicious).codehash);
    }
}
