/**
 * @description Rollback service for CloudCraze migration
 * Provides selective rollback capability by phase or object type
 * Supports dry-run mode for testing before actual deletion
 * @author Senior Developer, NULogic
 * @version 1.0
 */
public class MigrationRollbackService {

    private Map<String, Integer> deletionSummary = new Map<String, Integer>();
    private List<Rollback_Audit__c> auditTrail = new List<Rollback_Audit__c>();
    private Boolean dryRunMode = false;

    /**
     * Rollback entire migration phase
     * @param phase The MigrationOrchestrator.MigrationPhase to rollback
     */
    public void rollbackPhase(MigrationOrchestrator.MigrationPhase phase) {
        switch on phase {
            when PRODUCTS {
                rollbackProductMigration();
            }
            when PRICING {
                rollbackPricingMigration();
            }
            when ORDERS {
                rollbackOrderMigration();
            }
        }

        logRollbackCompletion(String.valueOf(phase));
    }

    /**
     * Perform rollback in dry-run mode (shows what would be deleted)
     * @param phase The phase to analyze
     * @return Map of object type to count of records that would be deleted
     */
    public Map<String, Integer> rollbackDryRun(MigrationOrchestrator.MigrationPhase phase) {
        dryRunMode = true;
        deletionSummary.clear();

        switch on phase {
            when PRODUCTS {
                simulateProductRollback();
            }
            when PRICING {
                simulatePricingRollback();
            }
            when ORDERS {
                simulateOrderRollback();
            }
        }

        dryRunMode = false;
        return deletionSummary;
    }

    /**
     * Rollback product migration
     * Delete all Product2 records created during migration
     */
    private void rollbackProductMigration() {
        List<Migration_Tracker__c> productTrackers = [
            SELECT Id FROM Migration_Tracker__c
            WHERE Object_Type__c = 'Product'
            AND Created_Records__c != null
        ];

        if (productTrackers.isEmpty()) {
            System.debug('No product migration records found to rollback');
            return;
        }

        // Get products created today (or in migration window)
        List<Product2> productsToDelete = [
            SELECT Id FROM Product2
            WHERE CreatedDate = TODAY
            ORDER BY CreatedDate DESC
        ];

        if (productsToDelete.isEmpty()) {
            return;
        }

        if (!dryRunMode) {
            try {
                delete productsToDelete;
                recordDeletion('Product2', productsToDelete.size());
                auditRollbackAction('Product2', productsToDelete.size(), 'DELETED');
            } catch (DmlException e) {
                auditRollbackAction('Product2', 0, 'FAILED: ' + e.getMessage());
                throw new RollbackException('Failed to delete products: ' + e.getMessage());
            }
        } else {
            deletionSummary.put('Product2', productsToDelete.size());
        }
    }

    /**
     * Simulate product rollback for dry-run
     */
    private void simulateProductRollback() {
        Integer count = [SELECT COUNT() FROM Product2 WHERE CreatedDate = TODAY];
        deletionSummary.put('Product2', count);
    }

    /**
     * Rollback pricing migration
     * Delete PricebookEntry and Pricebook2 records in proper order
     */
    private void rollbackPricingMigration() {
        // Delete entries first (child records)
        List<PricebookEntry> entriesToDelete = [
            SELECT Id FROM PricebookEntry
            WHERE CreatedDate = TODAY
            LIMIT 50000
        ];

        if (!entriesToDelete.isEmpty() && !dryRunMode) {
            try {
                delete entriesToDelete;
                recordDeletion('PricebookEntry', entriesToDelete.size());
                auditRollbackAction('PricebookEntry', entriesToDelete.size(), 'DELETED');
            } catch (DmlException e) {
                auditRollbackAction('PricebookEntry', 0, 'FAILED: ' + e.getMessage());
            }
        }

        // Delete pricebooks (parent records)
        List<Pricebook2> pricebooksToDelete = [
            SELECT Id FROM Pricebook2
            WHERE CreatedDate = TODAY
            AND IsStandard = false
            LIMIT 10000
        ];

        if (!pricebooksToDelete.isEmpty() && !dryRunMode) {
            try {
                delete pricebooksToDelete;
                recordDeletion('Pricebook2', pricebooksToDelete.size());
                auditRollbackAction('Pricebook2', pricebooksToDelete.size(), 'DELETED');
            } catch (DmlException e) {
                auditRollbackAction('Pricebook2', 0, 'FAILED: ' + e.getMessage());
            }
        }

        if (dryRunMode) {
            deletionSummary.put('PricebookEntry', entriesToDelete.size());
            deletionSummary.put('Pricebook2', pricebooksToDelete.size());
        }
    }

    /**
     * Simulate pricing rollback for dry-run
     */
    private void simulatePricingRollback() {
        Integer entryCount = [SELECT COUNT() FROM PricebookEntry WHERE CreatedDate = TODAY];
        Integer pbCount = [SELECT COUNT() FROM Pricebook2 WHERE CreatedDate = TODAY AND IsStandard = false];

        deletionSummary.put('PricebookEntry', entryCount);
        deletionSummary.put('Pricebook2', pbCount);
    }

    /**
     * Rollback order migration
     * Delete in cascade order: OrderItem → OrderDeliveryGroup → Order
     */
    private void rollbackOrderMigration() {
        // Delete order items first
        List<OrderItem> itemsToDelete = [
            SELECT Id FROM OrderItem
            WHERE CreatedDate = TODAY
            LIMIT 50000
        ];

        if (!itemsToDelete.isEmpty() && !dryRunMode) {
            try {
                delete itemsToDelete;
                recordDeletion('OrderItem', itemsToDelete.size());
                auditRollbackAction('OrderItem', itemsToDelete.size(), 'DELETED');
            } catch (DmlException e) {
                auditRollbackAction('OrderItem', 0, 'FAILED: ' + e.getMessage());
            }
        }

        // Delete delivery groups
        List<OrderDeliveryGroup> deliveryGroupsToDelete = [
            SELECT Id FROM OrderDeliveryGroup
            WHERE CreatedDate = TODAY
        ];

        if (!deliveryGroupsToDelete.isEmpty() && !dryRunMode) {
            try {
                delete deliveryGroupsToDelete;
                recordDeletion('OrderDeliveryGroup', deliveryGroupsToDelete.size());
                auditRollbackAction('OrderDeliveryGroup', deliveryGroupsToDelete.size(), 'DELETED');
            } catch (DmlException e) {
                auditRollbackAction('OrderDeliveryGroup', 0, 'FAILED: ' + e.getMessage());
            }
        }

        // Delete orders (parent)
        List<Order> ordersToDelete = [
            SELECT Id FROM Order
            WHERE CreatedDate = TODAY
            LIMIT 50000
        ];

        if (!ordersToDelete.isEmpty() && !dryRunMode) {
            try {
                delete ordersToDelete;
                recordDeletion('Order', ordersToDelete.size());
                auditRollbackAction('Order', ordersToDelete.size(), 'DELETED');
            } catch (DmlException e) {
                auditRollbackAction('Order', 0, 'FAILED: ' + e.getMessage());
            }
        }

        if (dryRunMode) {
            deletionSummary.put('OrderItem', itemsToDelete.size());
            deletionSummary.put('OrderDeliveryGroup', deliveryGroupsToDelete.size());
            deletionSummary.put('Order', ordersToDelete.size());
        }
    }

    /**
     * Simulate order rollback for dry-run
     */
    private void simulateOrderRollback() {
        Integer itemCount = [SELECT COUNT() FROM OrderItem WHERE CreatedDate = TODAY];
        Integer odgCount = [SELECT COUNT() FROM OrderDeliveryGroup WHERE CreatedDate = TODAY];
        Integer orderCount = [SELECT COUNT() FROM Order WHERE CreatedDate = TODAY];

        deletionSummary.put('OrderItem', itemCount);
        deletionSummary.put('OrderDeliveryGroup', odgCount);
        deletionSummary.put('Order', orderCount);
    }

    /**
     * Rollback by specific object type
     * @param objectType The API name of the object to rollback
     */
    public void rollbackByObjectType(String objectType) {
        switch on objectType {
            when 'Product2' {
                rollbackProductMigration();
            }
            when 'Pricebook2' {
                rollbackPricingMigration();
            }
            when 'Order' {
                rollbackOrderMigration();
            }
            when else {
                throw new RollbackException('Unsupported object type: ' + objectType);
            }
        }

        auditRollbackAction(objectType, deletionSummary.get(objectType), 'ROLLED_BACK');
    }

    /**
     * Record deletion count for summary
     */
    private void recordDeletion(String objectType, Integer count) {
        deletionSummary.put(objectType, count);
    }

    /**
     * Record rollback action to audit trail
     */
    private void auditRollbackAction(String objectType, Integer recordCount, String status) {
        Rollback_Audit__c audit = new Rollback_Audit__c();
        audit.Object_Type__c = objectType;
        audit.Records_Deleted__c = recordCount;
        audit.Rollback_Status__c = status;
        audit.Rollback_Date__c = System.now();
        audit.Dry_Run__c = dryRunMode;
        auditTrail.add(audit);
    }

    /**
     * Log rollback completion
     */
    private void logRollbackCompletion(String phase) {
        if (!auditTrail.isEmpty()) {
            insert auditTrail;
        }

        Integer totalDeleted = 0;
        String summary = '';

        for (String objectType : deletionSummary.keySet()) {
            Integer count = deletionSummary.get(objectType);
            totalDeleted += count;
            summary += objectType + ': ' + count + '\n';
        }

        System.debug('Rollback Summary (' + phase + '):\n' + summary);

        sendRollbackEmail(phase, totalDeleted, summary);
    }

    /**
     * Send rollback confirmation email
     */
    private void sendRollbackEmail(String phase, Integer totalRecords, String summary) {
        if (dryRunMode) {
            System.debug('DRY RUN MODE - No email sent');
            return;
        }

        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(new String[]{'migration-admin@nulogic.com'});
        mail.setSubject('CloudCraze Migration Rollback Complete - ' + phase);

        String body = 'Migration rollback completed for phase: ' + phase + '\n\n';
        body += 'Total Records Deleted: ' + totalRecords + '\n\n';
        body += 'Rollback Details:\n' + summary + '\n';
        body += 'Timestamp: ' + System.now().format() + '\n\n';
        body += 'All changes have been logged in Rollback_Audit__c for audit trail.';

        mail.setPlainTextBody(body);

        try {
            Messaging.sendEmail(new Messaging.SingleEmailMessage[]{mail});
        } catch (Exception e) {
            System.debug('Email delivery failed: ' + e.getMessage());
        }
    }

    /**
     * Get rollback summary for current operation
     */
    public Map<String, Integer> getSummary() {
        return deletionSummary;
    }

    /**
     * Custom exception for rollback errors
     */
    public class RollbackException extends Exception {}
}
