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

/**
 * @title Billing
 * @dev Smart contract for tracking billing and resource usage costs
 */
contract Billing {
    struct UsageRecord {
        string resourceId;
        string resourceType;
        uint256 startTime;
        uint256 endTime;
        uint256 cost; // Cost in smallest unit (wei-like)
        string currency;
        address billedTo;
    }

    struct Bill {
        address billedTo;
        uint256 periodStart;
        uint256 periodEnd;
        uint256 totalCost;
        string currency;
        bool paid;
        uint256 paidAt;
    }

    mapping(string => UsageRecord[]) public resourceUsage;
    mapping(address => Bill[]) public bills;
    mapping(string => uint256) public resourceCosts;

    event UsageRecorded(
        string indexed resourceId,
        address indexed billedTo,
        uint256 cost,
        uint256 timestamp
    );

    event BillGenerated(
        address indexed billedTo,
        uint256 billId,
        uint256 totalCost,
        uint256 periodStart,
        uint256 periodEnd
    );

    event BillPaid(
        address indexed billedTo,
        uint256 billId,
        uint256 paidAt
    );

    /**
     * @dev Record resource usage and cost
     */
    function recordUsage(
        string memory resourceId,
        string memory resourceType,
        uint256 startTime,
        uint256 endTime,
        uint256 cost,
        string memory currency,
        address billedTo
    ) public returns (bool) {
        UsageRecord memory record = UsageRecord({
            resourceId: resourceId,
            resourceType: resourceType,
            startTime: startTime,
            endTime: endTime,
            cost: cost,
            currency: currency,
            billedTo: billedTo
        });

        resourceUsage[resourceId].push(record);
        resourceCosts[resourceId] += cost;

        emit UsageRecorded(resourceId, billedTo, cost, block.timestamp);
        return true;
    }

    /**
     * @dev Generate a bill for a billing period
     */
    function generateBill(
        address billedTo,
        uint256 periodStart,
        uint256 periodEnd
    ) public returns (uint256) {
        uint256 totalCost = 0;

        // Calculate total cost from all usage records in period
        // This is simplified - actual implementation would aggregate all resources
        
        uint256 billId = bills[billedTo].length;
        Bill memory bill = Bill({
            billedTo: billedTo,
            periodStart: periodStart,
            periodEnd: periodEnd,
            totalCost: totalCost,
            currency: "USD",
            paid: false,
            paidAt: 0
        });

        bills[billedTo].push(bill);

        emit BillGenerated(billedTo, billId, totalCost, periodStart, periodEnd);
        return billId;
    }

    /**
     * @dev Mark a bill as paid
     */
    function payBill(address billedTo, uint256 billId) public {
        require(billId < bills[billedTo].length, "Bill does not exist");
        require(!bills[billedTo][billId].paid, "Bill already paid");

        bills[billedTo][billId].paid = true;
        bills[billedTo][billId].paidAt = block.timestamp;

        emit BillPaid(billedTo, billId, block.timestamp);
    }

    /**
     * @dev Get total cost for a resource
     */
    function getResourceTotalCost(string memory resourceId) public view returns (uint256) {
        return resourceCosts[resourceId];
    }

    /**
     * @dev Get all bills for an address
     */
    function getBills(address billedTo) public view returns (Bill[] memory) {
        return bills[billedTo];
    }
}

