/**
 * @description Main invocable class for combining multiple Docusign templates into a single envelope
 * @author Paul Huliganga
 * @date 2026-02-23
 */
global with sharing class DocusignCompositeEnvelopeBuilder {
    
    /**
     * @description Invocable method called from Salesforce Screen Flow
     * @param requests List of request objects containing template IDs and metadata
     * @return List of result objects with envelope ID and status
     */
    @InvocableMethod(
        label='Send Composite Docusign Envelope' 
        description='Combines multiple Docusign templates into a single envelope'
        category='Docusign'
    )
    public static List<Result> sendCompositeEnvelope(List<Request> requests) {
        List<Result> results = new List<Result>();
        
        // Process first request (Flow only sends one)
        if (requests == null || requests.isEmpty()) {
            return buildErrorResult('No request provided');
        }
        
        Request req = requests[0];
        Result result = new Result();
        
        try {
            // Validate request using handler
            DocusignEnvelopeRequestHandler.validateRequest(req);
            
            // Build envelope JSON using handler
            String envelopeJSON = DocusignEnvelopeRequestHandler.buildEnvelopeJSON(req);
            
            // Get Docusign credentials
            DocusignCredentials creds = DocusignCredentials.getInstance();
            
            // Call Docusign API
            String envelopeId = DocusignAPIService.createCompositeEnvelope(
                envelopeJSON,
                creds
            );
            
            // Success
            result.envelopeId = envelopeId;
            result.success = true;
            result.errorMessage = null;
            
            // Log success
            logAPICall(req.templateIds.size(), envelopeId, 'Success', null);
            
        } catch (Exception e) {
            // Error handling
            result.success = false;
            result.errorMessage = e.getMessage();
            result.envelopeId = null;
            
            // Log error
            logAPICall(
                req.templateIds != null ? req.templateIds.size() : 0,
                null,
                'Error',
                e.getMessage() + '\n' + e.getStackTraceString()
            );
            
            // Re-throw if critical (governor limits)
            if (e instanceof System.LimitException) {
                throw e;
            }
        }
        
        results.add(result);
        return results;
    }
    
    /**
     * @description Logs API call to debug log (future: custom object)
     * @param templateCount Number of templates in envelope
     * @param envelopeId Docusign envelope ID
     * @param status Success or Error
     * @param errorMessage Error message if applicable
     */
    private static void logAPICall(
        Integer templateCount,
        String envelopeId,
        String status,
        String errorMessage
    ) {
        System.debug(LoggingLevel.INFO, '=== Docusign Composite Envelope API Call ===');
        System.debug(LoggingLevel.INFO, 'Timestamp: ' + System.now());
        System.debug(LoggingLevel.INFO, 'Template Count: ' + templateCount);
        System.debug(LoggingLevel.INFO, 'Envelope ID: ' + envelopeId);
        System.debug(LoggingLevel.INFO, 'Status: ' + status);
        if (String.isNotBlank(errorMessage)) {
            System.debug(LoggingLevel.ERROR, 'Error: ' + errorMessage);
        }
        
        // Future enhancement: Insert into Docusign_API_Log__c custom object
    }
    
    /**
     * @description Helper to build error result
     * @param errorMessage Error message
     * @return List containing single error result
     */
    private static List<Result> buildErrorResult(String errorMessage) {
        Result result = new Result();
        result.success = false;
        result.errorMessage = errorMessage;
        result.envelopeId = null;
        return new List<Result>{ result };
    }
    
    /**
     * @description Input parameters for invocable method (from Screen Flow)
     */
    global class Request {
        @InvocableVariable(
            label='Template IDs' 
            description='List of Docusign template IDs to combine' 
            required=true
        )
        public List<String> templateIds;
        
        @InvocableVariable(
            label='Salesforce Record ID' 
            description='ID of the Salesforce record to attach documents to' 
            required=true
        )
        public String recordId;
        
        @InvocableVariable(
            label='Language' 
            description='Language code (en or es)' 
            required=false
        )
        public String language;
        
        @InvocableVariable(
            label='Email Subject' 
            description='Subject line for envelope email' 
            required=false
        )
        public String emailSubject;
    }
    
    /**
     * @description Output parameters for invocable method (to Screen Flow)
     */
    global class Result {
        @InvocableVariable(
            label='Envelope ID' 
            description='Docusign envelope ID'
        )
        public String envelopeId;
        
        @InvocableVariable(
            label='Success' 
            description='True if envelope was created successfully'
        )
        public Boolean success;
        
        @InvocableVariable(
            label='Error Message' 
            description='Error message if envelope creation failed'
        )
        public String errorMessage;
    }
}
