@IsTest
private class DocusignESignatureServiceTest {
    private class ESignatureMock implements HttpCalloutMock {
        public HttpResponse respond(HttpRequest req) {
            HttpResponse res = new HttpResponse();
            res.setHeader('Content-Type', 'application/json');

            if (req.getMethod() == 'GET' && req.getEndpoint().contains('/oauth/userinfo')) {
                res.setStatusCode(200);
                res.setBody('{"sub":"d9aab149-ff54-408c-a748-baa4b56e2fcd","accounts":[{"account_id":"12345678","account_name":"Demo eSignature Account","base_uri":"https://demo.docusign.net","is_default":true}]}');
                return res;
            }

            if (req.getMethod() == 'GET' && req.getEndpoint().contains('/templates')) {
                res.setStatusCode(200);
                res.setBody('{"envelopeTemplates":[{"templateId":"tmpl-001","name":"Review Letter","description":"Appraiser review letter template","shared":"true","lastModified":"2026-04-08T12:00:00Z"},{"templateId":"tmpl-002","name":"Alternate Review Letter","description":"Alternate version","shared":"false","lastModified":"2026-04-07T12:00:00Z"}]}');
                return res;
            }

            if (req.getMethod() == 'GET' && req.getEndpoint().contains('/envelopes?from_date=')) {
                res.setStatusCode(200);
                res.setBody('{"envelopes":[{"envelopeId":"env-001","emailSubject":"Appraiser Review","status":"completed","createdDateTime":"2026-04-01T10:00:00Z","sentDateTime":"2026-04-01T10:05:00Z","completedDateTime":"2026-04-01T10:15:00Z"},{"envelopeId":"env-002","emailSubject":"Second Review","status":"sent","createdDateTime":"2026-04-02T09:00:00Z","sentDateTime":"2026-04-02T09:05:00Z"}]}');
                return res;
            }

            if (req.getMethod() == 'GET' && req.getEndpoint().contains('/v2.1/accounts/12345678')) {
                res.setStatusCode(200);
                res.setBody('{"accountId":"12345678","accountName":"Demo eSignature Account","status":"active"}');
                return res;
            }

            if (req.getMethod() == 'GET' && req.getEndpoint().contains('/v2.1/login_information')) {
                res.setStatusCode(200);
                res.setBody('{"loginAccounts":[{"accountId":"12345678","name":"Demo eSignature Account","baseUrl":"https://demo.docusign.net/restapi/v2.1/accounts/12345678","isDefault":"true"},{"accountId":"87654321","name":"Secondary Demo Account","baseUrl":"https://demo.docusign.net/restapi/v2.1/accounts/87654321","isDefault":"false"}]}');
                return res;
            }

            res.setStatusCode(404);
            res.setBody('{"message":"Not Found"}');
            return res;
        }
    }

    @IsTest
    static void returnsConfiguredAccountInfo() {
        Test.startTest();
        DocusignESignatureService.ESignatureAccountConfig config = DocusignESignatureService.getAccountConfig('DTC_CLM_Demo');
        Test.stopTest();

        System.assertEquals('DTC_CLM_Demo', config.accountCode);
        System.assertEquals('DTC CLM Demo', config.accountDisplayName);
        System.assertEquals('AcctDemo_NamedCreds', config.eSignatureAuthNamedCredential);
        System.assertEquals('Esignature_Demo_NamedCreds', config.eSignatureRestNamedCredential);
    }

    @IsTest
    static void listsAccountsFromEsignatureApi() {
        Test.setMock(HttpCalloutMock.class, new ESignatureMock());

        Test.startTest();
        List<DocusignESignatureService.ESignatureAccountSummary> accounts = DocusignESignatureService.listAccounts('DTC_CLM_Demo');
        Test.stopTest();

        System.assertEquals(2, accounts.size());
        System.assertEquals('12345678', accounts[0].accountId);
        System.assertEquals('Demo eSignature Account', accounts[0].accountName);
        System.assertEquals('https://demo.docusign.net/restapi/v2.1/accounts/12345678', accounts[0].baseUri);
        System.assertEquals(true, accounts[0].isDefault);
    }

    @IsTest
    static void getsLoginInformationUsingWorkingEndpoint() {
        Test.setMock(HttpCalloutMock.class, new ESignatureMock());

        Test.startTest();
        DocusignESignatureService.ApiResponse response = DocusignESignatureService.getLoginInformation('DTC_CLM_Demo');
        Test.stopTest();

        System.assertEquals(true, response.success);
        System.assertEquals(200, response.statusCode);
        System.assert(response.responseBody.contains('loginAccounts'));
    }

    @IsTest
    static void getsUserInfoUsingAuthNamedCredential() {
        Test.setMock(HttpCalloutMock.class, new ESignatureMock());

        Test.startTest();
        DocusignESignatureService.ApiResponse response = DocusignESignatureService.getUserInfo('DTC_CLM_Demo');
        Test.stopTest();

        System.assertEquals(true, response.success);
        System.assertEquals(200, response.statusCode);
        System.assertEquals('/oauth/userinfo', response.requestPath);
        System.assert(response.responseBody.contains('"accounts"'));
    }

    @IsTest
    static void getsAccountInformationUsingConfiguredAccountId() {
        Test.setMock(HttpCalloutMock.class, new ESignatureMock());

        Test.startTest();
        DocusignESignatureService.ApiResponse response = DocusignESignatureService.getAccountInformation(
            'DTC_CLM_Demo',
            '12345678'
        );
        Test.stopTest();

        System.assertEquals(true, response.success);
        System.assertEquals(200, response.statusCode);
        System.assert(response.responseBody.contains('Demo eSignature Account'));
    }

    @IsTest
    static void listsTemplatesUsingConfiguredAccountId() {
        Test.setMock(HttpCalloutMock.class, new ESignatureMock());

        Test.startTest();
        List<DocusignESignatureService.TemplateSummary> templates = DocusignESignatureService.listTemplates('DTC_CLM_Demo');
        Test.stopTest();

        System.assertEquals(2, templates.size());
        System.assertEquals('tmpl-001', templates[0].templateId);
        System.assertEquals('Review Letter', templates[0].name);
    }

    @IsTest
    static void listsRecentEnvelopesUsingConfiguredAccountId() {
        Test.setMock(HttpCalloutMock.class, new ESignatureMock());

        Test.startTest();
        List<DocusignESignatureService.EnvelopeSummary> envelopes = DocusignESignatureService.listEnvelopes(
            'DTC_CLM_Demo',
            '2026-04-01'
        );
        Test.stopTest();

        System.assertEquals(2, envelopes.size());
        System.assertEquals('env-001', envelopes[0].envelopeId);
        System.assertEquals('completed', envelopes[0].status);
    }

    @IsTest
    static void buildsEndpointWithNamedCredential() {
        System.assertEquals(
            'callout:Esignature_Demo_NamedCreds/v2.1/accounts',
            DocusignESignatureService.buildEndpoint('/v2.1/accounts', 'Esignature_Demo_NamedCreds')
        );
    }
}
