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

/**
 * @title AddressActivityRegistry
 * @notice Emits Etherscan-indexed Chain 138 payment activity tied to participant addresses (ETH wei + USD e8).
 * @dev Called by checkpoint aggregator after each batch submit and optional v1 TransactionMirror dual-write.
 *      Does not move mainnet ETH — attestation / visibility only.
 */
contract AddressActivityRegistry {
    uint64 public constant CHAIN_ID = 138;
    uint8 public constant USD_DECIMALS = 8;

    address public admin;
    bool public paused;

    struct ActivityRecord {
        bytes32 txHash;
        address from;
        address to;
        uint256 valueWei;
        uint256 blockNumber138;
        uint64 blockTimestamp138;
        uint64 valueUsdE8;
        uint32 logCount;
        bytes32 receiptHash;
    }

    mapping(bytes32 => bool) public recorded;
    mapping(address => bytes32[]) public participantTxHashes;
    mapping(bytes32 => ActivityRecord) public activities;
    uint256 public totalRecorded;

    event AdminChanged(address indexed newAdmin);
    event Paused();
    event Unpaused();

    /// @notice Indexed for Etherscan lookup by participant address (topic2 = participant).
    /// @param chain138TxHash Chain 138 transaction hash (view at explorer.d-bis.org/tx/0x…)
    event ParticipantDebited(
        bytes32 indexed chain138TxHash,
        address indexed counterparty,
        address indexed participant,
        uint64 batchId,
        uint256 valueWei,
        uint64 valueUsdE8,
        uint32 logCount,
        bytes32 receiptHash,
        uint256 blockNumber138
    );

    /// @param chain138TxHash Chain 138 transaction hash (view at explorer.d-bis.org/tx/0x…)
    event ParticipantCredited(
        bytes32 indexed chain138TxHash,
        address indexed participant,
        address indexed counterparty,
        uint64 batchId,
        uint256 valueWei,
        uint64 valueUsdE8,
        uint32 logCount,
        bytes32 receiptHash,
        uint256 blockNumber138
    );

    event BatchActivityRecorded(uint64 indexed batchId, uint256 count, uint256 totalValueWei, uint64 totalUsdE8);

    modifier onlyAdmin() {
        require(msg.sender == admin, "only admin");
        _;
    }

    modifier whenNotPaused() {
        require(!paused, "paused");
        _;
    }

    constructor(address _admin) {
        require(_admin != address(0), "zero admin");
        admin = _admin;
    }

    function setAdmin(address newAdmin) external onlyAdmin {
        require(newAdmin != address(0), "zero admin");
        admin = newAdmin;
        emit AdminChanged(newAdmin);
    }

    function pause() external onlyAdmin {
        paused = true;
        emit Paused();
    }

    function unpause() external onlyAdmin {
        paused = false;
        emit Unpaused();
    }

    /**
     * @notice Record Chain 138 activity for a checkpoint batch (one mainnet tx per batch).
     * @param batchId Checkpoint hub batch id
     * @param records Parallel activity rows (from 138 txs + off-chain USD enrichment)
     */
    function recordBatch(uint64 batchId, ActivityRecord[] calldata records) external onlyAdmin whenNotPaused {
        uint256 batchValueWei;
        uint64 batchUsdE8;
        uint256 n = records.length;
        for (uint256 i = 0; i < n; i++) {
            ActivityRecord calldata r = records[i];
            require(r.txHash != bytes32(0), "invalid hash");
            require(!recorded[r.txHash], "already recorded");

            recorded[r.txHash] = true;
            activities[r.txHash] = r;
            totalRecorded++;

            batchValueWei += r.valueWei;
            batchUsdE8 += r.valueUsdE8;

            participantTxHashes[r.from].push(r.txHash);
            participantTxHashes[r.to].push(r.txHash);

            emit ParticipantDebited(
                r.txHash,
                r.to,
                r.from,
                batchId,
                r.valueWei,
                r.valueUsdE8,
                r.logCount,
                r.receiptHash,
                r.blockNumber138
            );
            emit ParticipantCredited(
                r.txHash,
                r.to,
                r.from,
                batchId,
                r.valueWei,
                r.valueUsdE8,
                r.logCount,
                r.receiptHash,
                r.blockNumber138
            );
        }
        emit BatchActivityRecorded(batchId, n, batchValueWei, batchUsdE8);
    }

    function getParticipantTxCount(address participant) external view returns (uint256) {
        return participantTxHashes[participant].length;
    }

    function getParticipantTxHash(address participant, uint256 index) external view returns (bytes32) {
        return participantTxHashes[participant][index];
    }

    function getActivity(bytes32 txHash) external view returns (ActivityRecord memory) {
        return activities[txHash];
    }
}
