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

import "forge-std/Test.sol";
import "../../contracts/vault/RateAccrual.sol";

contract RateAccrualTest is Test {
    RateAccrual public rateAccrual;

    address public admin = address(0x1);
    address public asset = address(0x100);

    uint256 public constant INTEREST_RATE = 500; // 5% annual

    function setUp() public {
        rateAccrual = new RateAccrual(admin);
    }

    function test_SetInterestRate() public {
        vm.prank(admin);
        rateAccrual.setInterestRate(asset, INTEREST_RATE);

        assertEq(rateAccrual.interestRate(asset), INTEREST_RATE);
    }

    function test_AccrueInterest_Initial() public {
        vm.prank(admin);
        rateAccrual.setInterestRate(asset, INTEREST_RATE);

        vm.prank(address(0x2));
        uint256 accumulator = rateAccrual.accrueInterest(asset);

        assertEq(accumulator, 1e27); // RAY = initial value
    }

    function test_AccrueInterest_OverTime() public {
        vm.prank(admin);
        rateAccrual.setInterestRate(asset, INTEREST_RATE);

        // Initial accrual
        vm.prank(address(0x2));
        rateAccrual.accrueInterest(asset);

        uint256 accumulator1 = rateAccrual.getRateAccumulator(asset);

        // Fast forward 1 year
        vm.warp(block.timestamp + 365 days);

        vm.prank(address(0x2));
        rateAccrual.accrueInterest(asset);

        uint256 accumulator2 = rateAccrual.getRateAccumulator(asset);

        // Accumulator should increase (approximately 5% over 1 year)
        assertGt(accumulator2, accumulator1, "Accumulator should increase with time");
    }

    function test_GetRateAccumulator_ViewOnly() public {
        vm.prank(admin);
        rateAccrual.setInterestRate(asset, INTEREST_RATE);

        // Get accumulator without state change (view function)
        uint256 accumulator1 = rateAccrual.getRateAccumulator(asset);
        assertEq(accumulator1, 1e27); // Initial RAY

        // Fast forward time
        vm.warp(block.timestamp + 365 days);

        // Get accumulator again (should accrue interest in view function)
        uint256 accumulator2 = rateAccrual.getRateAccumulator(asset);
        assertGt(accumulator2, accumulator1, "View function should accrue interest");
    }

    function test_CalculateDebtWithInterest() public {
        vm.prank(admin);
        rateAccrual.setInterestRate(asset, INTEREST_RATE);

        uint256 principalDebt = 1000e18;

        // Calculate with initial accumulator (no interest yet)
        uint256 debt1 = rateAccrual.calculateDebtWithInterest(asset, principalDebt);
        assertEq(debt1, principalDebt);

        // Fast forward 1 year and accrue interest
        vm.warp(block.timestamp + 365 days);
        vm.prank(address(0x2));
        rateAccrual.accrueInterest(asset);

        // Calculate debt with accrued interest
        uint256 debt2 = rateAccrual.calculateDebtWithInterest(asset, principalDebt);
        
        // Debt should be greater due to interest (~5% increase)
        assertGt(debt2, principalDebt, "Debt should increase with interest");
    }

    function test_ZeroInterestRate() public {
        vm.prank(admin);
        rateAccrual.setInterestRate(asset, 0); // 0% interest

        vm.prank(address(0x2));
        uint256 accumulator1 = rateAccrual.accrueInterest(asset);

        vm.warp(block.timestamp + 365 days);
        vm.prank(address(0x2));
        uint256 accumulator2 = rateAccrual.accrueInterest(asset);

        // Accumulator should remain unchanged with 0% interest
        assertEq(accumulator1, accumulator2);
    }
}
