// File: contracts/escrow.sol



pragma solidity ^0.8.0;

interface IERC20 {
    function transfer(address recipient, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
}

contract Escrow {
    enum State { Created, Locked, ReleasePending, RefundPending, Disputed, Resolved }

    address public buyer;
    address public seller;
    address public arbiter;
    uint public amount;
    IERC20 public token;
    State public state;

    address public admin;
    bool public adminSet;
    uint public adminFee;

    constructor(uint _adminFee) {
        admin = msg.sender;
        adminFee = _adminFee;
    }

    function setAdmin(address _admin) external {
        require(msg.sender == admin && !adminSet, "Not authorized or already set");
        admin = _admin;
        adminSet = true;
    }

    function createEscrow(address _buyer, address _seller, address _arbiter, uint _amount, address _token) external {
        require(msg.sender == admin, "Not authorized you are not admin");
        buyer = _buyer;
        seller = _seller;
        arbiter = _arbiter;
        amount = _amount;
        token = IERC20(_token);
        state = State.Created;
    }

    modifier inState(State _state) {
        require(state == _state, "Invalid state");
        _;
    }

    function confirmDelivery() external inState(State.Locked) {
        require(msg.sender == buyer, "Not authorized");
        state = State.ReleasePending;
    }

    function release() external inState(State.ReleasePending) {
        require(msg.sender == buyer || msg.sender == seller || msg.sender == arbiter, "Not authorized");
        require(token.balanceOf(address(this)) >= amount, "Insufficient balance");

        uint adminAmount = amount * adminFee / 100;
        uint sellerAmount = amount - adminAmount;

        token.transfer(seller, sellerAmount);
        token.transfer(admin, adminAmount);

        state = State.Resolved;
    }

    function refund() external inState(State.RefundPending) {
        require(msg.sender == buyer || msg.sender == seller || msg.sender == arbiter, "Not authorized");
        token.transfer(buyer, token.balanceOf(address(this)));
        state = State.Resolved;
    }

    function dispute() external inState(State.Locked) {
        require(msg.sender == buyer || msg.sender == seller, "Not authorized");
        state = State.Disputed;
    }

    function resolveDispute(bool _sellerWins) external inState(State.Disputed) {
        require(msg.sender == admin, "Not authorized");
        if (_sellerWins) {
            token.transfer(seller, token.balanceOf(address(this)));
            state = State.Resolved;
        } else {
            token.transfer(buyer, token.balanceOf(address(this)));
            state = State.Resolved;
        }
    }

    function approve(address _spender, uint256 _amount) external returns (bool) {
        return token.approve(_spender, _amount);
    }

    function allowance(address _owner, address _spender) external view returns (uint256) {
        return token.allowance(_owner, _spender);
    }

    
    }