/**
 * @description Combines multiple Docusign templates into a single composite envelope
 *              using the dfsle Apex Toolkit (Docusign for Salesforce managed package)
 * @author Paul Huliganga
 * @date 2026-02-25
 */
global with sharing class DocusignCompositeEnvelopeBuilder {
    
    @InvocableMethod(
        label='Send Composite Docusign Envelope' 
        description='Combines multiple Docusign templates into a single envelope using dfsle Apex Toolkit'
        category='Docusign'
    )
    public static List<DocusignEnvelopeResult> sendCompositeEnvelope(List<DocusignEnvelopeRequest> requests) {
        List<DocusignEnvelopeResult> results = new List<DocusignEnvelopeResult>();
        
        if (requests == null || requests.isEmpty()) {
            return buildErrorResult('No request provided');
        }
        
        DocusignEnvelopeRequest req = requests[0];
        DocusignEnvelopeResult result = new DocusignEnvelopeResult();
        
        try {
            // Validate request
            DocusignEnvelopeRequestHandler.validateRequest(req);
            
            // Create empty envelope linked to the source Salesforce record
            dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope(
                new dfsle.Entity(req.recordId)
            );
            
            // Build document list from templates (deduplicated and sorted)
            List<String> sortedTemplateIds = new List<String>(new Set<String>(req.templateIds));
            sortedTemplateIds.sort();
            
            List<dfsle.Document> documents = new List<dfsle.Document>();
            for (String templateId : sortedTemplateIds) {
                documents.add(
                    dfsle.Document.fromTemplate(
                        dfsle.UUID.parse(templateId),
                        'Template ' + templateId.left(8)
                    )
                );
            }
            
            // Add all templates as documents to the envelope
            myEnvelope = myEnvelope.withDocuments(documents);
            
            // Set email subject if provided
            if (String.isNotBlank(req.emailSubject)) {
                myEnvelope = myEnvelope.withEmail(req.emailSubject, '');
            }
            
            // Send the envelope (true = send immediately)
            myEnvelope = dfsle.EnvelopeService.sendEnvelope(myEnvelope, true);
            
            // Success
            result.envelopeId = String.valueOf(myEnvelope.docuSignId);
            result.success = true;
            result.errorMessage = null;
            
            logResult(sortedTemplateIds.size(), result.envelopeId, 'Success', null);
            
        } catch (Exception e) {
            result.success = false;
            result.errorMessage = e.getMessage();
            result.envelopeId = null;
            
            logResult(
                req.templateIds != null ? req.templateIds.size() : 0,
                null, 'Error',
                e.getMessage() + '\n' + e.getStackTraceString()
            );
            
            if (e instanceof System.LimitException) {
                throw e;
            }
        }
        
        results.add(result);
        return results;
    }
    
    private static void logResult(Integer templateCount, String envelopeId, String status, String errorMessage) {
        System.debug(LoggingLevel.INFO, '=== Docusign Composite Envelope ===');
        System.debug(LoggingLevel.INFO, 'Templates: ' + templateCount);
        System.debug(LoggingLevel.INFO, 'Envelope ID: ' + envelopeId);
        System.debug(LoggingLevel.INFO, 'Status: ' + status);
        if (String.isNotBlank(errorMessage)) {
            System.debug(LoggingLevel.ERROR, 'Error: ' + errorMessage);
        }
    }
    
    private static List<DocusignEnvelopeResult> buildErrorResult(String errorMessage) {
        DocusignEnvelopeResult result = new DocusignEnvelopeResult();
        result.success = false;
        result.errorMessage = errorMessage;
        result.envelopeId = null;
        return new List<DocusignEnvelopeResult>{ result };
    }
}
