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

import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title WorkflowRegistry
 * @notice Registers and tracks workflow definitions on-chain
 * @dev Placeholder for future workflow verification capabilities
 */
contract WorkflowRegistry is Ownable {
    struct WorkflowDefinition {
        bytes32 id;
        string workflowType;
        string name;
        bytes32 definitionHash;
        uint256 version;
        uint256 timestamp;
        bool isActive;
    }

    // Mapping from workflow ID to definition
    mapping(bytes32 => WorkflowDefinition) private _workflows;

    // Mapping from workflow type to latest workflow ID
    mapping(string => bytes32) private _latestWorkflows;

    // Array of all workflow IDs
    bytes32[] private _workflowIds;

    // Counter for unique IDs
    uint256 private _workflowCounter;

    // Events
    event WorkflowRegistered(
        bytes32 indexed workflowId,
        string indexed workflowType,
        string name,
        bytes32 definitionHash,
        uint256 version
    );

    event WorkflowDeactivated(bytes32 indexed workflowId);

    event WorkflowActivated(bytes32 indexed workflowId);

    constructor() Ownable(msg.sender) {}

    /**
     * @notice Register a new workflow definition
     * @param workflowType The type of workflow (e.g., "RESORT_LICENSE")
     * @param name Human-readable name
     * @param definitionHash Hash of the workflow definition JSON
     * @return workflowId The unique workflow ID
     */
    function registerWorkflow(
        string calldata workflowType,
        string calldata name,
        bytes32 definitionHash
    ) public onlyOwner returns (bytes32) {
        require(bytes(workflowType).length > 0, "Workflow type required");
        require(bytes(name).length > 0, "Name required");
        require(definitionHash != bytes32(0), "Definition hash required");

        _workflowCounter++;
        bytes32 workflowId = keccak256(
            abi.encodePacked(workflowType, _workflowCounter, block.timestamp)
        );

        // Determine version
        uint256 version = 1;
        bytes32 latestId = _latestWorkflows[workflowType];
        if (latestId != bytes32(0)) {
            version = _workflows[latestId].version + 1;
            // Deactivate previous version
            _workflows[latestId].isActive = false;
        }

        WorkflowDefinition storage workflow = _workflows[workflowId];
        workflow.id = workflowId;
        workflow.workflowType = workflowType;
        workflow.name = name;
        workflow.definitionHash = definitionHash;
        workflow.version = version;
        workflow.timestamp = block.timestamp;
        workflow.isActive = true;

        _latestWorkflows[workflowType] = workflowId;
        _workflowIds.push(workflowId);

        emit WorkflowRegistered(
            workflowId,
            workflowType,
            name,
            definitionHash,
            version
        );

        return workflowId;
    }

    /**
     * @notice Get workflow definition by ID
     * @param workflowId The workflow ID
     * @return The WorkflowDefinition struct
     */
    function getWorkflow(bytes32 workflowId)
        public
        view
        returns (WorkflowDefinition memory)
    {
        require(_workflows[workflowId].timestamp > 0, "Workflow not found");
        return _workflows[workflowId];
    }

    /**
     * @notice Get the latest active workflow for a type
     * @param workflowType The workflow type
     * @return The WorkflowDefinition struct
     */
    function getLatestWorkflow(string calldata workflowType)
        public
        view
        returns (WorkflowDefinition memory)
    {
        bytes32 workflowId = _latestWorkflows[workflowType];
        require(workflowId != bytes32(0), "No workflow found for type");
        return _workflows[workflowId];
    }

    /**
     * @notice Verify a workflow definition hash
     * @param workflowId The workflow ID
     * @param definitionHash The hash to verify
     * @return True if the hash matches
     */
    function verifyWorkflow(bytes32 workflowId, bytes32 definitionHash)
        public
        view
        returns (bool)
    {
        WorkflowDefinition memory workflow = _workflows[workflowId];
        return workflow.isActive && workflow.definitionHash == definitionHash;
    }

    /**
     * @notice Deactivate a workflow
     * @param workflowId The workflow ID
     */
    function deactivateWorkflow(bytes32 workflowId) public onlyOwner {
        require(_workflows[workflowId].timestamp > 0, "Workflow not found");
        require(_workflows[workflowId].isActive, "Workflow already inactive");

        _workflows[workflowId].isActive = false;

        emit WorkflowDeactivated(workflowId);
    }

    /**
     * @notice Activate a workflow
     * @param workflowId The workflow ID
     */
    function activateWorkflow(bytes32 workflowId) public onlyOwner {
        require(_workflows[workflowId].timestamp > 0, "Workflow not found");
        require(!_workflows[workflowId].isActive, "Workflow already active");

        _workflows[workflowId].isActive = true;

        emit WorkflowActivated(workflowId);
    }

    /**
     * @notice Get total workflow count
     * @return The number of registered workflows
     */
    function getWorkflowCount() public view returns (uint256) {
        return _workflowIds.length;
    }

    /**
     * @notice Check if a workflow is active
     * @param workflowId The workflow ID
     * @return True if active
     */
    function isWorkflowActive(bytes32 workflowId) public view returns (bool) {
        return _workflows[workflowId].isActive;
    }
}
