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

import {Test} from "forge-std/Test.sol";
import {AddressActivityRegistry} from "../../contracts/mainnet-checkpoint/AddressActivityRegistry.sol";

contract AddressActivityRegistryTest is Test {
    AddressActivityRegistry registry;
    address admin = address(0xA11CE);
    address from = address(0x1111);
    address to = address(0x2222);

    event ParticipantDebited(
        bytes32 indexed chain138TxHash,
        address indexed counterparty,
        address indexed participant,
        uint64 batchId,
        uint256 valueWei,
        uint64 valueUsdE8,
        uint32 logCount,
        bytes32 receiptHash,
        uint256 blockNumber138
    );

    event ParticipantCredited(
        bytes32 indexed chain138TxHash,
        address indexed participant,
        address indexed counterparty,
        uint64 batchId,
        uint256 valueWei,
        uint64 valueUsdE8,
        uint32 logCount,
        bytes32 receiptHash,
        uint256 blockNumber138
    );

    function setUp() public {
        registry = new AddressActivityRegistry(admin);
    }

    function testRecordBatchEmitsAndStores() public {
        vm.startPrank(admin);
        AddressActivityRegistry.ActivityRecord[] memory rows =
            new AddressActivityRegistry.ActivityRecord[](1);
        rows[0] = AddressActivityRegistry.ActivityRecord({
            txHash: keccak256("tx1"),
            from: from,
            to: to,
            valueWei: 7500 ether,
            blockNumber138: 1_943_065,
            blockTimestamp138: 1_739_000_000,
            valueUsdE8: 15_000_000_000_000, // 150k USD at 8 decimals
            logCount: 0,
            receiptHash: keccak256("receipt")
        });

        vm.expectEmit(true, true, true, true, address(registry));
        emit ParticipantDebited(
            rows[0].txHash,
            to,
            from,
            42,
            7500 ether,
            15_000_000_000_000,
            0,
            rows[0].receiptHash,
            1_943_065
        );
        vm.expectEmit(true, true, true, true, address(registry));
        emit ParticipantCredited(
            rows[0].txHash,
            to,
            from,
            42,
            7500 ether,
            15_000_000_000_000,
            0,
            rows[0].receiptHash,
            1_943_065
        );

        registry.recordBatch(42, rows);
        vm.stopPrank();

        assertTrue(registry.recorded(rows[0].txHash));
        assertEq(registry.getParticipantTxCount(from), 1);
        assertEq(registry.getParticipantTxCount(to), 1);
        assertEq(registry.totalRecorded(), 1);
    }

    function testReplayBlocked() public {
        vm.startPrank(admin);
        AddressActivityRegistry.ActivityRecord[] memory rows =
            new AddressActivityRegistry.ActivityRecord[](1);
        rows[0] = AddressActivityRegistry.ActivityRecord({
            txHash: keccak256("dup"),
            from: from,
            to: to,
            valueWei: 1,
            blockNumber138: 1,
            blockTimestamp138: 1,
            valueUsdE8: 0,
            logCount: 0,
            receiptHash: bytes32(0)
        });
        registry.recordBatch(1, rows);
        vm.expectRevert("already recorded");
        registry.recordBatch(2, rows);
        vm.stopPrank();
    }
}
