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

/// @title TWIXDataAnchor
/// @notice Minimal permissionless commitment registry for TDAP batches.
/// @dev Holds no funds, has no owner, no upgrade hook, and no arbitrary calls.
contract TWIXDataAnchor {
    uint256 public constant TWIX_EVM_CHAIN_ID = 1415006552;

    struct Anchor {
        bytes32 manifestHash;
        address submitter;
        uint64 recordCount;
        uint64 periodStart;
        uint64 periodEnd;
        uint64 blockTime;
    }

    mapping(bytes32 => Anchor) public anchors;

    error WrongChain(uint256 actualChainId);
    error ZeroRoot();
    error ZeroManifestHash();
    error EmptyBatch();
    error InvalidPeriod();
    error AlreadyAnchored(bytes32 merkleRoot);

    event DataAnchored(
        bytes32 indexed merkleRoot,
        bytes32 indexed manifestHash,
        address indexed submitter,
        uint64 recordCount,
        uint64 periodStart,
        uint64 periodEnd,
        uint64 blockTime
    );

    constructor() {
        if (block.chainid != TWIX_EVM_CHAIN_ID) {
            revert WrongChain(block.chainid);
        }
    }

    function anchor(
        bytes32 merkleRoot,
        bytes32 manifestHash,
        uint64 recordCount,
        uint64 periodStart,
        uint64 periodEnd
    ) external {
        if (merkleRoot == bytes32(0)) revert ZeroRoot();
        if (manifestHash == bytes32(0)) revert ZeroManifestHash();
        if (recordCount == 0) revert EmptyBatch();
        if (periodEnd < periodStart) revert InvalidPeriod();
        if (anchors[merkleRoot].submitter != address(0)) {
            revert AlreadyAnchored(merkleRoot);
        }

        uint64 ts = uint64(block.timestamp);
        anchors[merkleRoot] = Anchor({
            manifestHash: manifestHash,
            submitter: msg.sender,
            recordCount: recordCount,
            periodStart: periodStart,
            periodEnd: periodEnd,
            blockTime: ts
        });

        emit DataAnchored(
            merkleRoot,
            manifestHash,
            msg.sender,
            recordCount,
            periodStart,
            periodEnd,
            ts
        );
    }

    function isAnchored(bytes32 merkleRoot) external view returns (bool) {
        return anchors[merkleRoot].submitter != address(0);
    }
}
