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

import {Test, console} from "forge-std/Test.sol";
import "../../../../contracts/bridge/trustless/integration/ISOCurrencyManager.sol";
import "../../../../contracts/reserve/ReserveSystem.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MockERC20 is ERC20 {
    constructor(string memory name, string memory symbol) ERC20(name, symbol) {
        _mint(msg.sender, 1000000 ether);
    }
}

contract ISOCurrencyManagerTest is Test {
    ISOCurrencyManager public isoCurrencyManager;
    ReserveSystem public reserveSystem;
    
    MockERC20 public xau;
    MockERC20 public usdt;
    MockERC20 public eurToken;

    address public deployer = address(0xDE0001);

    function setUp() public {
        vm.startPrank(deployer);

        // Deploy mock tokens
        xau = new MockERC20("Gold", "XAU");
        usdt = new MockERC20("Tether USD", "USDT");
        eurToken = new MockERC20("Euro", "EUR");

        // Deploy ReserveSystem
        reserveSystem = new ReserveSystem(deployer);
        // Grant PRICE_FEED_ROLE to deployer
        reserveSystem.grantRole(keccak256("PRICE_FEED_ROLE"), deployer);

        // Set prices
        reserveSystem.updatePriceFeed(address(xau), 2000e18, block.timestamp); // $2000/oz
        reserveSystem.updatePriceFeed(address(usdt), 1e18, block.timestamp); // $1.00

        // Deploy ISOCurrencyManager
        isoCurrencyManager = new ISOCurrencyManager(address(reserveSystem));
        isoCurrencyManager.setXAUAddress(address(xau));

        // Register currencies
        // 1 oz XAU = 2000 USD
        isoCurrencyManager.registerCurrency("USD", address(usdt), 2000e18);
        // 1 oz XAU = 1800 EUR
        isoCurrencyManager.registerCurrency("EUR", address(eurToken), 1800e18);
        // 1 oz XAU = 300000 JPY (example)
        isoCurrencyManager.registerCurrency("JPY", address(0), 300000e18);

        vm.stopPrank();
    }

    function testRegisterCurrency() public {
        string[] memory currencies = isoCurrencyManager.getAllSupportedCurrencies();
        assertEq(currencies.length, 3);
    }

    function testConvertViaXAU() public {
        // Convert 2000 USD to EUR via XAU
        // 2000 USD = 1 oz XAU = 1800 EUR
        uint256 usdAmount = 2000 ether;
        uint256 eurAmount = isoCurrencyManager.convertViaXAU("USD", "EUR", usdAmount);
        
        assertApproxEqRel(eurAmount, 1800e18, 0.01e18); // 1% tolerance
    }

    function testGetCurrencyRate() public {
        // USD to EUR rate
        // 1 USD = (1800 / 2000) EUR = 0.9 EUR
        uint256 rate = isoCurrencyManager.getCurrencyRate("USD", "EUR");
        
        assertApproxEqRel(rate, 0.9e18, 0.01e18);
    }

    function testGetCurrencyAddress() public {
        address usdAddress = isoCurrencyManager.getCurrencyAddress("USD");
        assertEq(usdAddress, address(usdt));
        
        address eurAddress = isoCurrencyManager.getCurrencyAddress("EUR");
        assertEq(eurAddress, address(eurToken));
        
        address jpyAddress = isoCurrencyManager.getCurrencyAddress("JPY");
        assertEq(jpyAddress, address(0)); // Not tokenized
    }

    function testGetCurrencyInfo() public {
        (address tokenAddress, uint256 xauRate, bool isActive, bool isTokenized) = 
            isoCurrencyManager.getCurrencyInfo("USD");
        
        assertEq(tokenAddress, address(usdt));
        assertEq(xauRate, 2000e18);
        assertTrue(isActive);
        assertTrue(isTokenized);
    }

    function testUpdateXauRate() public {
        uint256 newRate = 2100e18; // Update to 2100 USD per oz XAU
        
        vm.prank(deployer);
        isoCurrencyManager.updateXauRate("USD", newRate);
        
        // Verify rate was updated
        (address tokenAddress, uint256 xauRate, , ) = isoCurrencyManager.getCurrencyInfo("USD");
        assertEq(xauRate, newRate);
    }

    function testBatchRegisterCurrencies() public {
        string[] memory codes = new string[](2);
        codes[0] = "GBP";
        codes[1] = "CNY";
        
        address[] memory addresses = new address[](2);
        addresses[0] = address(0);
        addresses[1] = address(0);
        
        uint256[] memory rates = new uint256[](2);
        rates[0] = 1500e18; // 1 oz XAU = 1500 GBP
        rates[1] = 14000e18; // 1 oz XAU = 14000 CNY
        
        // batchRegisterCurrencies calls registerCurrency which requires owner
        vm.startPrank(deployer);
        isoCurrencyManager.batchRegisterCurrencies(codes, addresses, rates);
        vm.stopPrank();
        
        string[] memory allCurrencies = isoCurrencyManager.getAllSupportedCurrencies();
        assertGe(allCurrencies.length, 5); // Should have at least 5 currencies now
    }
}

