@IsTest
private class AppraiserCasePayloadBuilderTest {
    
    @TestSetup
    static void setupTestData() {
        // Create test Appraiser Case
        Appraiser_Case__c testCase = new Appraiser_Case__c(
            Appraiser_Field_Review_Date__c = Date.newInstance(2026, 4, 2),
            Letter_Sent_Date__c = Date.newInstance(2026, 4, 9),
            FHA_Case_Number__c = '123-4567890',
            Appraiser_Name__c = 'Jamie Appraiser',
            Appraiser_Salutation__c = 'Ms.',
            Appraiser_Last_Name__c = 'Appraiser',
            Appraiser_Email__c = 'jamie.appraiser@example.com',
            Appraiser_Street__c = '245 Lexington Ave',
            Appraiser_City__c = 'New York',
            Appraiser_State_Province__c = 'NY',
            Appraiser_Postal_Code__c = '10016',
            Appraiser_Country__c = 'USA',
            Property_Street__c = '123 Main St',
            Property_City__c = 'Denver',
            Property_State_Province__c = 'CO',
            Property_Postal_Code__c = '80202',
            Property_Country__c = 'USA'
        );
        insert testCase;
        
        // Create test deficiency records
        List<Appraiser_Case_Deficiency__c> testDefs = new List<Appraiser_Case_Deficiency__c>();
        testDefs.add(new Appraiser_Case_Deficiency__c(
            Appraiser_Case__c = testCase.Id,
            Deficiency_Number__c = 1,
            Description__c = 'Missing comparable sale adjustment detail.',
            Resolution__c = 'Added adjustment rationale and supporting calculations.',
            Reference__c = 'VC-1'
        ));
        testDefs.add(new Appraiser_Case_Deficiency__c(
            Appraiser_Case__c = testCase.Id,
            Deficiency_Number__c = 2,
            Description__c = 'Neighborhood trend explanation insufficient.',
            Resolution__c = 'Expanded market trend narrative with MLS evidence.',
            Reference__c = 'MC-2'
        ));
        insert testDefs;
    }
    
    @IsTest
    static void testBuildPayload() {
        Appraiser_Case__c testCase = [SELECT Id FROM Appraiser_Case__c LIMIT 1];
        
        Map<String, Object> payload = AppraiserCasePayloadBuilder.buildPayload(testCase.Id);
        
        Assert.isNotNull(payload, 'Payload should not be null');
        Assert.isTrue(payload.containsKey('AppraiserCaseNumber'), 'Payload should contain AppraiserCaseNumber');
        Assert.isTrue(payload.containsKey('AppraiserFieldReviewDate'), 'Payload should contain AppraiserFieldReviewDate');
        Assert.isTrue(payload.containsKey('LetterSentDate'), 'Payload should contain LetterSentDate');
        Assert.isTrue(payload.containsKey('FHACaseNumber'), 'Payload should contain FHACaseNumber');
        Assert.isTrue(payload.containsKey('AppraiserName'), 'Payload should contain AppraiserName');
        Assert.isTrue(payload.containsKey('AppraiserSalutation'), 'Payload should contain AppraiserSalutation');
        Assert.isTrue(payload.containsKey('AppraiserLastName'), 'Payload should contain AppraiserLastName');
        Assert.isTrue(payload.containsKey('AppraiserEmail'), 'Payload should contain AppraiserEmail');
        Assert.isTrue(payload.containsKey('AppraiserAddress'), 'Payload should contain AppraiserAddress');
        Assert.isTrue(payload.containsKey('PropertyAddress'), 'Payload should contain PropertyAddress');
        Assert.isTrue(payload.containsKey('PropertyStreet'), 'Payload should contain PropertyStreet');
        Assert.isTrue(payload.containsKey('PropertyCity'), 'Payload should contain PropertyCity');
        Assert.isTrue(payload.containsKey('PropertyStateProvince'), 'Payload should contain PropertyStateProvince');
        Assert.isTrue(payload.containsKey('PropertyPostalCode'), 'Payload should contain PropertyPostalCode');
        Assert.isTrue(payload.containsKey('PropertyCountry'), 'Payload should contain PropertyCountry');
        Assert.isTrue(payload.containsKey('DeficiencyList'), 'Payload should contain DeficiencyList');
        Assert.areEqual('123 Main St', (String) payload.get('PropertyStreet'));
        Assert.areEqual('Denver', (String) payload.get('PropertyCity'));
        Assert.areEqual('CO', (String) payload.get('PropertyStateProvince'));
        Assert.areEqual('80202', (String) payload.get('PropertyPostalCode'));
        Assert.areEqual('USA', (String) payload.get('PropertyCountry'));
        Assert.areEqual('123-4567890', (String) payload.get('FHACaseNumber'));
        Assert.areEqual('Apr 02, 2026', (String) payload.get('AppraiserFieldReviewDate'));
        Assert.areEqual('Apr 09, 2026', (String) payload.get('LetterSentDate'));
        Assert.areEqual('Jamie Appraiser', (String) payload.get('AppraiserName'));
        Assert.areEqual('Ms.', (String) payload.get('AppraiserSalutation'));
        Assert.areEqual('Appraiser', (String) payload.get('AppraiserLastName'));
        Assert.areEqual('jamie.appraiser@example.com', (String) payload.get('AppraiserEmail'));
        Assert.areEqual('245 Lexington Ave, New York, NY 10016, USA', (String) payload.get('AppraiserAddress'));
        Assert.areEqual('123 Main St, Denver, CO 80202, USA', (String) payload.get('PropertyAddress'));
        
        List<Object> deficiencyList = (List<Object>) payload.get('DeficiencyList');
        Assert.areEqual(2, deficiencyList.size(), 'DeficiencyList should contain 2 items');
        Map<String, Object> firstDeficiency = (Map<String, Object>) deficiencyList[0];
        Assert.areEqual('VC-1', (String) firstDeficiency.get('reference'));
    }
    
    @IsTest
    static void testBuildPayloadJson() {
        Appraiser_Case__c testCase = [SELECT Id FROM Appraiser_Case__c LIMIT 1];
        
        String jsonPayload = AppraiserCasePayloadBuilder.buildPayloadJson(testCase.Id);
        
        Assert.isNotNull(jsonPayload, 'JSON payload should not be null');
        Assert.isTrue(jsonPayload.contains('AppraiserCaseNumber'), 'JSON should contain AppraiserCaseNumber');
        Assert.isTrue(jsonPayload.contains('DeficiencyList'), 'JSON should contain DeficiencyList');
    }
    
    @IsTest
    static void testPayloadWithNullDate() {
        // Create case without review date
        Appraiser_Case__c testCase = new Appraiser_Case__c(
            Property_Street__c = '456 Oak Ave',
            Property_City__c = 'Boulder',
            Property_State_Province__c = 'CO',
            Property_Postal_Code__c = '80301'
        );
        insert testCase;
        
        Map<String, Object> payload = AppraiserCasePayloadBuilder.buildPayload(testCase.Id);
        
        Assert.isNotNull(payload, 'Payload should not be null even with null date');
        Assert.isNull(payload.get('AppraiserFieldReviewDate'), 'Null date should map to null in payload');
        Assert.areEqual('456 Oak Ave, Boulder, CO 80301', (String) payload.get('PropertyAddress'));
    }
    
    @IsTest
    static void testInvalidCaseId() {
        try {
            AppraiserCasePayloadBuilder.buildPayload('a0wKW000000000000');
            Assert.fail('Should have thrown exception for invalid case id');
        } catch (IllegalArgumentException ex) {
            Assert.isTrue(ex.getMessage().contains('Appraiser Case not found'));
        }
    }
}
