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

import {Test} from "forge-std/Test.sol";
import {TokenRegistry} from "../../contracts/utils/TokenRegistry.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MockERC20 is ERC20 {
    constructor(string memory name, string memory symbol, uint8 decimalsValue) ERC20(name, symbol) {
        _mint(msg.sender, 1000000 * 10**decimalsValue);
    }
    
    function decimals() public pure override returns (uint8) {
        return 6;
    }
}

contract TokenRegistryTest is Test {
    TokenRegistry public registry;
    MockERC20 public token1;
    MockERC20 public token2;
    address public admin;
    address public registrar;
    
    function setUp() public {
        admin = address(this);
        registrar = address(this);
        
        registry = new TokenRegistry(admin);
        token1 = new MockERC20("Token 1", "TK1", 6);
        token2 = new MockERC20("Token 2", "TK2", 18);
    }
    
    function testRegisterToken() public {
        registry.registerToken(
            address(token1),
            "Token 1",
            "TK1",
            6,
            false,
            address(0)
        );
        
        assertTrue(registry.isTokenRegistered(address(token1)));
        assertTrue(registry.isTokenActive(address(token1)));
        
        TokenRegistry.TokenInfo memory info = registry.getTokenInfo(address(token1));
        assertEq(info.name, "Token 1");
        assertEq(info.symbol, "TK1");
        assertEq(info.decimals, 6);
    }
    
    function testGetTokenBySymbol() public {
        registry.registerToken(
            address(token1),
            "Token 1",
            "TK1",
            6,
            false,
            address(0)
        );
        
        address found = registry.getTokenBySymbol("TK1");
        assertEq(found, address(token1));
    }
    
    function testUpdateTokenStatus() public {
        registry.registerToken(
            address(token1),
            "Token 1",
            "TK1",
            6,
            false,
            address(0)
        );
        
        registry.updateTokenStatus(address(token1), false);
        assertFalse(registry.isTokenActive(address(token1)));
        
        registry.updateTokenStatus(address(token1), true);
        assertTrue(registry.isTokenActive(address(token1)));
    }
    
    function testRemoveToken() public {
        registry.registerToken(
            address(token1),
            "Token 1",
            "TK1",
            6,
            false,
            address(0)
        );
        
        registry.removeToken(address(token1));
        assertFalse(registry.isTokenRegistered(address(token1)));
    }
    
    function testGetAllTokens() public {
        registry.registerToken(
            address(token1),
            "Token 1",
            "TK1",
            6,
            false,
            address(0)
        );
        
        registry.registerToken(
            address(token2),
            "Token 2",
            "TK2",
            18,
            false,
            address(0)
        );
        
        address[] memory tokens = registry.getAllTokens();
        assertEq(tokens.length, 2);
        assertEq(tokens[0], address(token1));
        assertEq(tokens[1], address(token2));
    }
    
    function testGetTokenCount() public {
        assertEq(registry.getTokenCount(), 0);
        
        registry.registerToken(
            address(token1),
            "Token 1",
            "TK1",
            6,
            false,
            address(0)
        );
        
        assertEq(registry.getTokenCount(), 1);
    }
    
    function testDuplicateSymbol() public {
        registry.registerToken(
            address(token1),
            "Token 1",
            "TK1",
            6,
            false,
            address(0)
        );
        
        vm.expectRevert("TokenRegistry: symbol already used");
        registry.registerToken(
            address(token2),
            "Token 2",
            "TK1", // Duplicate symbol
            18,
            false,
            address(0)
        );
    }
}

