/***********************************************************************************************************
 * Name         : CurrencyUtilsTest
 * Purpose      : Test class for CurrencyUtils
 **********************************************************************************************************/
@isTest
public class CurrencyUtilsTest {
    /************************************************************************************
     * APEX method tested : CurrencyUtils.calculateValueInUSD
     * Description : ensures that the calculateValueInUSD method accurately converts specified currency fields to USD,
     *  updating the appropriate fields in an SObject based on the latest conversion rates.
     *************************************************************************************/
    @isTest
    public static void testCalculateValueInUSD() {
        Opportunity opp = TestFactory.getAwalOpp();
        opp.Amount = 10;
        opp.CurrencyIsoCode = 'EUR';

        Map<String, String> amountToConvertAndConvertedFieldsMap = new Map<String, String>{ 'Amount' => 'Amount' };

        DatedConversionRate conversionRateRecord = [
            SELECT Id, IsoCode, StartDate, NextStartDate, ConversionRate
            FROM DatedConversionRate
            WHERE IsoCode = :opp.CurrencyIsoCode
            ORDER BY IsoCode, StartDate DESC
            LIMIT 1
        ];

        Decimal originalAmount = opp.Amount;

        Test.startTest();
        CurrencyUtils.calculateValueInUSD(
            new List<Opportunity>{ opp },
            CurrencyUtils.CLOSE_DATE_FIELD,
            amountToConvertAndConvertedFieldsMap,
            new List<String>{ opp.CurrencyIsoCode }
        );
        Test.stopTest();

        Decimal expectedConvertedAmount = (1 / conversionRateRecord.ConversionRate) * originalAmount;

        Assert.areEqual(expectedConvertedAmount, opp.get('Amount'));
    }

    /************************************************************************************
     * APEX method tested : CurrencyUtils.updateExchangeRateField
     * Description : Ensures that the updateExchangeRateField method correctly updates the specified 
     *   exchange rate field on a list of SObject records.
     *************************************************************************************/
    @isTest
    public static void testUpdateExchangeRateField() {
        Opportunity opp = TestFactory.getAwalOpp();
        opp.CurrencyIsoCode = 'EUR';
        opp.CloseDate = Date.today();
        insert opp;

        DatedConversionRate conversionRateRecord = [
            SELECT Id, IsoCode, StartDate, NextStartDate, ConversionRate
            FROM DatedConversionRate
            WHERE IsoCode = :opp.CurrencyIsoCode
            ORDER BY IsoCode, StartDate DESC
            LIMIT 1
        ];

        Test.startTest();
        CurrencyUtils.updateExchangeRateField(
            new List<SObject>{ opp },
            CurrencyUtils.CLOSE_DATE_FIELD,
            CurrencyUtils.EXCHANGE_RATE_FIELD,
            new List<String>{ opp.CurrencyIsoCode }
        );
        Test.stopTest();

        Assert.areEqual(conversionRateRecord.ConversionRate, (Decimal) opp.get(CurrencyUtils.EXCHANGE_RATE_FIELD));
    }
}