/**
 * SIMInventoryImporter
 * Invocable Apex class for importing Physical SIM inventory from CSV files.
 * Used by Screen Flow to allow employees to bulk import physical SIMs.
 * 
 * CSV Format Expected (matching ASI_N6_PASI_*.csv):
 * Row,Phone_Number,PT_Number,OEM_ID,Batch_Date,,,,,
 * 1,02000002470001,PT0220024700010,PASI,20251229,,,,
 * 
 * Note: No header row expected. All imports are Physical SIM type.
 * 
 * @author Customer Portal Team
 * @version 1.1
 */
public with sharing class SIMInventoryImporter {
    
    // Hardcoded values for Physical SIM imports
    private static final String SIM_TYPE = 'Physical SIM';
    private static final Boolean SKIP_HEADER = false;
    
    /**
     * Input wrapper for the invocable method
     */
    public class ImportRequest {
        @InvocableVariable(label='Content Document IDs' description='IDs from File Upload component' required=true)
        public List<String> contentDocumentIds;
    }
    
    /**
     * Output wrapper for the invocable method
     */
    public class ImportResult {
        @InvocableVariable(label='Success')
        public Boolean success;
        
        @InvocableVariable(label='Records Created')
        public Integer recordsCreated;
        
        @InvocableVariable(label='Records Failed')
        public Integer recordsFailed;
        
        @InvocableVariable(label='Error Messages')
        public String errorMessages;
        
        @InvocableVariable(label='Summary Message')
        public String summaryMessage;
    }
    
    /**
     * Main invocable method called by Flow
     */
    @InvocableMethod(label='Import SIM Inventory from CSV' 
                     description='Parses CSV content and creates SIM_Inventory__c records'
                     category='SIM Management')
    public static List<ImportResult> importFromCSV(List<ImportRequest> requests) {
        List<ImportResult> results = new List<ImportResult>();
        
        for (ImportRequest request : requests) {
            results.add(processCSV(request));
        }
        
        return results;
    }
    
    /**
     * Process a single CSV import request
     */
    private static ImportResult processCSV(ImportRequest request) {
        ImportResult result = new ImportResult();
        result.success = true;
        result.recordsCreated = 0;
        result.recordsFailed = 0;
        result.errorMessages = '';
        
        try {
            // Get the first Content Document ID from the list
            if (request.contentDocumentIds == null || request.contentDocumentIds.isEmpty()) {
                result.success = false;
                result.errorMessages = 'No file was uploaded. Please select a CSV file.';
                result.summaryMessage = 'Import failed: No file uploaded';
                return result;
            }
            String contentDocumentId = request.contentDocumentIds[0];
            
            // Retrieve file content from ContentVersion
            List<ContentVersion> cvList = [
                SELECT VersionData 
                FROM ContentVersion 
                WHERE ContentDocumentId = :contentDocumentId 
                AND IsLatest = true 
                LIMIT 1
            ];
            
            if (cvList.isEmpty()) {
                result.success = false;
                result.errorMessages = 'Could not find the uploaded file. Please try again.';
                result.summaryMessage = 'Import failed: File not found';
                return result;
            }
            
            String csvContent = cvList[0].VersionData.toString();
            
            // Parse CSV content
            List<String> lines = csvContent.split('\n');
            List<SIM_Inventory__c> simsToInsert = new List<SIM_Inventory__c>();
            List<String> errors = new List<String>();
            
            // Start from first row (no header row in Physical SIM CSV files)
            Integer startIndex = SKIP_HEADER ? 1 : 0;
            
            // Collect existing phone numbers to check for duplicates
            Set<String> existingPhoneNumbers = new Set<String>();
            for (SIM_Inventory__c existing : [SELECT Phone_Number__c FROM SIM_Inventory__c WHERE Phone_Number__c != null]) {
                existingPhoneNumbers.add(existing.Phone_Number__c);
            }
            
            Set<String> phoneNumbersInBatch = new Set<String>();
            
            for (Integer i = startIndex; i < lines.size(); i++) {
                String line = lines[i].trim();
                
                // Skip empty lines
                if (String.isBlank(line)) {
                    continue;
                }
                
                // Remove carriage return if present (Windows line endings)
                line = line.replace('\r', '');
                
                try {
                    // Parse CSV line
                    List<String> columns = parseCSVLine(line);
                    
                    // Expected format: Row,Phone_Number,PT_Number,OEM_ID,Batch_Date,,,,,
                    if (columns.size() < 2) {
                        errors.add('Row ' + (i + 1) + ': Not enough columns (need at least phone number)');
                        result.recordsFailed++;
                        continue;
                    }
                    
                    String phoneNumber = columns.size() > 1 ? columns[1].trim() : '';
                    String ptNumber = columns.size() > 2 ? columns[2].trim() : '';
                    String oemId = columns.size() > 3 ? columns[3].trim() : '';
                    String batchDateStr = columns.size() > 4 ? columns[4].trim() : '';
                    
                    // Validate phone number
                    if (String.isBlank(phoneNumber)) {
                        errors.add('Row ' + (i + 1) + ': Phone number is empty');
                        result.recordsFailed++;
                        continue;
                    }
                    
                    // Check for duplicates in database
                    if (existingPhoneNumbers.contains(phoneNumber)) {
                        errors.add('Row ' + (i + 1) + ': Phone number ' + phoneNumber + ' already exists in database');
                        result.recordsFailed++;
                        continue;
                    }
                    
                    // Check for duplicates within the CSV
                    if (phoneNumbersInBatch.contains(phoneNumber)) {
                        errors.add('Row ' + (i + 1) + ': Duplicate phone number ' + phoneNumber + ' in CSV file');
                        result.recordsFailed++;
                        continue;
                    }
                    
                    // Parse batch date (format: YYYYMMDD)
                    Date batchDate = null;
                    if (String.isNotBlank(batchDateStr) && batchDateStr.length() >= 8) {
                        try {
                            Integer year = Integer.valueOf(batchDateStr.substring(0, 4));
                            Integer month = Integer.valueOf(batchDateStr.substring(4, 6));
                            Integer day = Integer.valueOf(batchDateStr.substring(6, 8));
                            batchDate = Date.newInstance(year, month, day);
                        } catch (Exception e) {
                            // Leave as null if parsing fails - not critical
                        }
                    }
                    
                    // Create SIM_Inventory__c record
                    SIM_Inventory__c sim = new SIM_Inventory__c();
                    sim.Phone_Number__c = phoneNumber;
                    sim.PT_Number__c = ptNumber;
                    sim.OEM_ID__c = oemId;
                    sim.Batch_Date__c = batchDate;
                    sim.Status__c = 'Available';
                    sim.SIM_Type__c = SIM_TYPE; // Always Physical SIM
                    sim.Name = phoneNumber; // Use phone number as name for easy identification
                    
                    simsToInsert.add(sim);
                    phoneNumbersInBatch.add(phoneNumber);
                    
                } catch (Exception e) {
                    errors.add('Row ' + (i + 1) + ': ' + e.getMessage());
                    result.recordsFailed++;
                }
            }
            
            // Insert records with partial success allowed
            if (!simsToInsert.isEmpty()) {
                Database.SaveResult[] saveResults = Database.insert(simsToInsert, false);
                
                for (Integer i = 0; i < saveResults.size(); i++) {
                    if (saveResults[i].isSuccess()) {
                        result.recordsCreated++;
                    } else {
                        result.recordsFailed++;
                        for (Database.Error err : saveResults[i].getErrors()) {
                            errors.add('Insert error for ' + simsToInsert[i].Phone_Number__c + ': ' + err.getMessage());
                        }
                    }
                }
            }
            
            // Build error message string (limit to first 10 errors for readability)
            if (!errors.isEmpty()) {
                if (errors.size() <= 10) {
                    result.errorMessages = String.join(errors, '\n');
                } else {
                    List<String> firstTen = new List<String>();
                    for (Integer i = 0; i < 10; i++) {
                        firstTen.add(errors[i]);
                    }
                    result.errorMessages = String.join(firstTen, '\n') 
                                          + '\n\n... and ' + (errors.size() - 10) + ' more errors';
                }
            }
            
            // Build summary message
            result.summaryMessage = 'Import completed: ' + result.recordsCreated + ' records created successfully.';
            if (result.recordsFailed > 0) {
                result.summaryMessage += ' ' + result.recordsFailed + ' records failed.';
                result.success = (result.recordsCreated > 0); // Partial success if any records created
            }
            
        } catch (Exception e) {
            result.success = false;
            result.errorMessages = 'Critical error: ' + e.getMessage() + '\n\nStack trace: ' + e.getStackTraceString();
            result.summaryMessage = 'Import failed due to an unexpected error.';
        }
        
        return result;
    }
    
    /**
     * Parse a single CSV line, handling quoted fields properly
     */
    private static List<String> parseCSVLine(String line) {
        List<String> result = new List<String>();
        Boolean inQuotes = false;
        String currentField = '';
        
        for (Integer i = 0; i < line.length(); i++) {
            String c = line.substring(i, i + 1);
            
            if (c == '"') {
                inQuotes = !inQuotes;
            } else if (c == ',' && !inQuotes) {
                result.add(currentField);
                currentField = '';
            } else {
                currentField += c;
            }
        }
        
        // Add the last field
        result.add(currentField);
        
        return result;
    }
}
