/***********************************************************************************************************
 * Name         : FanTriggerHelper
 * Purpose      : Implementation for methods called by FanTriggerHandler
 **********************************************************************************************************/

public with sharing class FanTriggerHelper {
    /**
     * @description Updates Fan CCPA_Do_Not_Sell__c field when the email is flagged as CCPA
     * If the Fan is changing their email the flag needs to be recalulated for the new email
     * @param oldList    old List values
     * @param newList    new List values
     */
    public static void identifyCCPAFans(List<Fan__c> oldList, List<Fan__c> newList) {
        Map<String, Fan__c> emailFanMap = new Map<String, Fan__c>();
        for (Integer i = 0; i < newList.size(); i++) {
            if (oldList == null || (oldList[i].Email__c != newList[i].Email__c)) {
                emailFanMap.put(newList[i].Email__c, newList[i]);
            }
        }
        if (!emailFanMap.isEmpty()) {
            Set<String> ccpaEmailsSet = new Set<String>();
            for (Load_CCPA_List__c ccpaEmail : [
                SELECT Email__c
                FROM Load_CCPA_List__c
                WHERE Email__c IN :emailFanMap.keySet()
            ]) {
                ccpaEmailsSet.add(ccpaEmail.Email__c);
            }

            for (String email : emailFanMap.keySet()) {
                emailFanMap.get(email).CCPA_Do_Not_Sell__c = ccpaEmailsSet.contains(email);
            }
        }
    }

    /**
     * @description Updates Load_CCPA_List__c records based on whether a Fan with that
     *  email address exists or not
     * @param oldList    old List values
     * @param newList    new List values
     */
    public static void updateCCPAList(List<Fan__c> oldList, List<Fan__c> newList) {
        try {
            Map<String, String> emailFanIdMap = new Map<String, String>();
            for (Integer i = 0; i < newList.size(); i++) {
                if (oldList == null) {
                    if (newList[i].CCPA_Do_Not_Sell__c) {
                        emailFanIdMap.put(newList[i].Email__c, newList[i].Id);
                    }
                } else if (
                    oldList[i].Email__c != newList[i].Email__c &&
                    (oldList[i].CCPA_Do_Not_Sell__c || newList[i].CCPA_Do_Not_Sell__c)
                ) {
                    if (oldList[i].CCPA_Do_Not_Sell__c) {
                        emailFanIdMap.put(oldList[i].Email__c, null);
                    }
                    if (newList[i].CCPA_Do_Not_Sell__c) {
                        emailFanIdMap.put(newList[i].Email__c, newList[i].Id);
                    }
                }
            }
            if (!emailFanIdMap.isEmpty()) {
                List<Load_CCPA_List__c> ccpaRecords = [
                    SELECT Email__c, Fan_Matched__c, Fan_Id__c
                    FROM Load_CCPA_List__c
                    WHERE Email__c IN :emailFanIdMap.keySet()
                ];
                for (Load_CCPA_List__c ccpaRecord : ccpaRecords) {
                    String fanId = emailFanIdMap.get(ccpaRecord.Email__c);
                    if (Trigger.isDelete || String.isBlank(fanId)) {
                        ccpaRecord.Fan_Matched__c = false;
                        ccpaRecord.Fan_Id__c = null;
                    } else {
                        ccpaRecord.Fan_Matched__c = true;
                        ccpaRecord.Fan_Id__c = fanId;
                    }
                }
                update ccpaRecords;
            }
        } catch (Exception ex) {
            SMELogger.logError(ex);
        }
    }

    /* Re-using existing logic to create "encrypted id".
    This has to be reviewed at some point to confirm no duplicated values can be created
    as the replaceAll function could potentially transform different inputs into the same output
    */
    public static void createEncryptedId(List<Fan__c> fans) {
        List<Fan__c> fansToUpdate = new List<Fan__c>();
        for (Fan__c fan : fans) {
            Blob targetBlob = Blob.valueOf(String.valueOf(fan.Id));
            Blob hash = Crypto.generateDigest('MD5', targetBlob);
            String alphanumeric = EncodingUtil.base64Encode(hash);
            alphanumeric = alphanumeric.replaceAll(
                '[|,|.|\\,||"||:|~|!|@|#|$|%|^|&|*|_|+|=|<|>|?|\\(|\\)|\\{|\\}|\\;|\\\'"]',
                ''
            );
            fansToUpdate.add(new Fan__c(Id = fan.Id, Encrypted_ID__c = alphanumeric));
        }

        update fansToUpdate;
    }

    //Moving existing code here (should be reviewed and/or splitted into different methods)
    public static void handleEmailChangeDeleteInformation(Map<Id, Fan__c> oldMap, List<Fan__c> newList) {
        List<String> uniqCustEmailSet = new List<String>();
        for (Fan__c fan : newList) {
            if (oldMap.get(fan.Id).Email__c != fan.Email__c) {
                UpdateEmailInMC_AllSubscribersList.callFuture(fan.Fan_Full_ID__c, fan.Email__c);
            }
            if (oldMap.get(fan.Id).Delete_my_information__c != fan.Delete_my_information__c) {
                uniqCustEmailSet.add(fan.Email__c);
            }
        }
        FanTriggerHandlerForDeletion triggerDeletion = new FanTriggerHandlerForDeletion();
        triggerDeletion.onAfterDeleteMyInformation(uniqCustEmailSet);
    }

    //Moving existing code here (should be reviewed)
    public static void createMcCleanup(List<Fan__c> fans) {
        List<Fan_MC_Cleanup__c> fmcList = new List<Fan_MC_Cleanup__c>();
        for (Fan__c fan : fans) {
            Fan_MC_Cleanup__c fmc = new Fan_MC_Cleanup__c();
            fmc.Fan_ID__c = fan.id;
            fmcList.add(fmc);
        }
        insert fmcList;
    }
}
