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

/**
 * @title ResourceProvisioning
 * @dev Smart contract for tracking resource provisioning on the blockchain
 */
contract ResourceProvisioning {
    enum ResourceType {
        VM,
        CONTAINER,
        STORAGE,
        NETWORK,
        SERVICE
    }

    struct Resource {
        string resourceId;
        string region;
        string datacenter;
        ResourceType resourceType;
        uint256 provisionedAt;
        address provisionedBy;
        bool active;
        string metadata; // JSON string
    }

    mapping(string => Resource) public resources;
    mapping(string => bool) public resourceExists;
    
    string[] public resourceIds;

    event ResourceProvisioned(
        string indexed resourceId,
        string region,
        ResourceType resourceType,
        address indexed provisionedBy,
        uint256 timestamp
    );

    event ResourceDeprovisioned(
        string indexed resourceId,
        address indexed deprovisionedBy,
        uint256 timestamp
    );

    /**
     * @dev Provision a new resource
     */
    function provisionResource(
        string memory resourceId,
        string memory region,
        string memory datacenter,
        ResourceType resourceType,
        string memory metadata
    ) public returns (bool) {
        require(bytes(resourceId).length > 0, "Resource ID cannot be empty");
        require(!resourceExists[resourceId], "Resource already exists");

        resources[resourceId] = Resource({
            resourceId: resourceId,
            region: region,
            datacenter: datacenter,
            resourceType: resourceType,
            provisionedAt: block.timestamp,
            provisionedBy: msg.sender,
            active: true,
            metadata: metadata
        });

        resourceExists[resourceId] = true;
        resourceIds.push(resourceId);

        emit ResourceProvisioned(
            resourceId,
            region,
            resourceType,
            msg.sender,
            block.timestamp
        );

        return true;
    }

    /**
     * @dev Deprovision a resource
     */
    function deprovisionResource(string memory resourceId) public {
        require(resourceExists[resourceId], "Resource does not exist");
        require(resources[resourceId].active, "Resource already deprovisioned");

        resources[resourceId].active = false;

        emit ResourceDeprovisioned(resourceId, msg.sender, block.timestamp);
    }

    /**
     * @dev Get resource information
     */
    function getResource(string memory resourceId) 
        public 
        view 
        returns (Resource memory) 
    {
        require(resourceExists[resourceId], "Resource does not exist");
        return resources[resourceId];
    }

    /**
     * @dev Get all resource IDs
     */
    function getAllResourceIds() public view returns (string[] memory) {
        return resourceIds;
    }

    /**
     * @dev Get resource count
     */
    function getResourceCount() public view returns (uint256) {
        return resourceIds.length;
    }
}

