/***********************************************************************************************************
 * Name         : MasterApproverUtils
 * Purpose      : Hold logic to find Master Approver records
 **********************************************************************************************************/

public with sharing class MasterApproverUtils {
    private static String MASTER_APPROVER_LOOKUP_FIELD = 'MasterApproverId__c';

    /**
     * @description Return the list of matching Master Approver records.
     * @param sobj The list of SObjects to evaluate against the criteria
     * @param approvers The list of MasterApprovers previously collected
     * @param amountField The API name of the field that holds the amount value to evaluate
     * @param addCriteriaField The API name of the field to evaluate for the additional criteria
     * @param customer Name of the customer/team the logic will be applied to
     * @return List of MasterApprovers__c records that match the criteria
     */
    public static List<MasterApprovers__c> filterMultipleApprovers(
        SObject sObj,
        List<MasterApprovers__c> approvers,
        String amountField,
        String addCriteriaField,
        String customer
    ) {
        List<MasterApprovers__c> result = new List<MasterApprovers__c>();
        Decimal amount = amountField != null ? Decimal.valueOf(String.valueOf(sObj.get(amountField))) : 0;
        for (MasterApprovers__c approver : approvers) {
            if (amount >= approver.Amount_From__c && amount <= approver.Amount_To__c) {
                if (approver.Default_Approver__c) {
                    result.add(approver);
                } else {
                    Boolean isAddCriteriaMet = MasterApproverUtils.getAddCriteria(
                        customer,
                        String.valueOf(sObj.get(addCriteriaField)),
                        approver.Additional_Criteria__c
                    );

                    if (isAddCriteriaMet) {
                        result.add(approver);
                    }
                }
            }
        }
        return result;
    }

    public static void setMasterApprover(List<MasterApproverParameter> parameters) {
        Set<String> customers = new Set<String>();
        Set<String> teams = new Set<String>();
        for (MasterApproverParameter parameter : parameters) {
            customers.add(parameter.customer);
            teams.add(parameter.team);
        }

        List<MasterApprovers__c> masterApprovers = getRecordsByCustomerAndTeam(customers, teams);

        if (!masterApprovers.isEmpty()) {
            for (MasterApproverParameter parameter : parameters) {
                Decimal amount = parameter?.sObj?.get(parameter?.amountField) != null
                    ? Decimal.valueOf(String.valueOf(parameter.sObj.get(parameter.amountField)))
                    : 0;
                MasterApprovers__c selectedApprover;
                MasterApprovers__c defaultApprover;
                for (MasterApprovers__c approver : masterApprovers) {
                    if (
                        parameter.customer == approver.Customer__c &&
                        parameter.team == approver.Team__c &&
                        amount >= approver.Amount_From__c &&
                        amount <= approver.Amount_To__c
                    ) {
                        if (approver.Default_Approver__c) {
                            defaultApprover = approver;
                        } else {
                            Boolean isAddCriteriaMet = MasterApproverUtils.getAddCriteria(
                                parameter.customer,
                                String.valueOf(parameter.sObj.get(parameter.addCriteriaField)),
                                approver.Additional_Criteria__c
                            );

                            if (isAddCriteriaMet) {
                                selectedApprover = approver;
                                break;
                            }
                        }
                    }
                }
                selectedApprover = selectedApprover ?? defaultApprover;
                if (selectedApprover != null) {
                    parameter.sObj.put(MASTER_APPROVER_LOOKUP_FIELD, selectedApprover.Id);
                }
            }
        }
    }

    /**
     * @description Pick the correct Additional Criteria based on customer.
     * @param customer The type of customer to determine what criteria to apply
     * @param objAddCriteria The additional criteria value from the SObjects
     * @param approverAddCriteria The additional criteria value from the MasterApprovers__c record
     * @return Boolean indicating if the additional criteria are met
     */
    public static Boolean getAddCriteria(String customer, Object objAddCriteria, String approverAddCriteria) {
        if (customer == AWAL_Constants.AWAL) {
            return calculateAddCriteriaforAwal(String.valueOf(objAddCriteria), approverAddCriteria);
        } else {
            return true;
        }
    }

    /**
     * @description Calculates whether the additional criteria for AWAL customer are met.
     * @param objAddCriteria The additional criteria value from the SObject
     * @param approverAddCriteria The additional criteria value from the MasterApprovers__c record
     * @return Boolean indicating if the AWAL-specific additional criteria are met
     */
    public static Boolean calculateAddCriteriaforAwal(String objAddCriteria, String approverAddCriteria) {
        return approverAddCriteria == null || approverAddCriteria.split(';').contains(objAddCriteria);
    }

    /**
     * @description Retrieves a list of active Master Approver records based on the provided customer and team.
     * @param customer The customer to filter the Master Approver records. If null, no filtering is applied.
     * @param team The team to filter the Master Approver records. If null, no filtering is applied.
     * @return List<MasterApprovers__c> A list of Master Approver records that match the given criteria.
     */
    public static List<MasterApprovers__c> getRecordsByCustomerAndTeam(String customer, String team) {
        String query =
            'SELECT Id, Name, User__c, User__r.Email, ApproverInitials__c, Amount_From__c, Amount_To__c,' +
            ' Additional_Criteria__c, Default_Approver__c, Team__c' +
            ' FROM MasterApprovers__c' +
            ' WHERE IsActive__c = TRUE';

        if (!String.isBlank(customer)) {
            query += ' AND Customer__c = :customer';
        }

        if (team != null) {
            query += ' AND Team__c = :team';
        }

        query += ' ORDER BY Amount_From__c ASC, Amount_To__c ASC, Default_Approver__c ASC';

        return Database.query(query);
    }

    /**
     * @description Retrieves a list of active Master Approver records based on the provided customer and team.
     * @param Set<String> Customers to filter the Master Approver records. If null, no filtering is applied.
     * @param Set<String> Teams to filter the Master Approver records. If null, no filtering is applied.
     * @return List<MasterApprovers__c> A list of Master Approver records that match the given criteria.
     */
    public static List<MasterApprovers__c> getRecordsByCustomerAndTeam(Set<String> customers, Set<String> teams) {
        String query =
            'SELECT Id, Name, User__c, User__r.Email, ApproverInitials__c, Customer__c, Amount_From__c, Amount_To__c,' +
            ' Additional_Criteria__c, Default_Approver__c, Team__c' +
            ' FROM MasterApprovers__c' +
            ' WHERE IsActive__c = TRUE';

        if (customers != null && !customers.isEmpty()) {
            query += ' AND Customer__c IN :customers';
        }

        if (teams != null && !teams.isEmpty()) {
            query += ' AND Team__c IN :teams';
        }

        query += ' ORDER BY Customer__c, Team__c, Amount_From__c ASC, Amount_To__c ASC, Default_Approver__c ASC';

        return Database.query(query);
    }

    /**
     * @description Retrieves a map of Master Approver records. If a set of IDs is provided,
     *  it filters the records by those IDs.
     * @param ids The set of Master Approver record IDs to retrieve. If null or empty, retrieves all records.
     * @return Map<Id, MasterApprovers__c> A map of Master Approver records, keyed by their IDs.
     */
    public static Map<Id, MasterApprovers__c> getMapById(Set<Id> ids) {
        String query = 'SELECT Id, User__c FROM MasterApprovers__c';

        if (ids != null && !ids.isEmpty()) {
            query += ' WHERE Id IN :ids';
        }

        List<MasterApprovers__c> records = Database.query(query);

        return new Map<Id, MasterApprovers__c>(records);
    }

    public class MasterApproverParameter {
        SObject sObj;
        String amountField;
        String addCriteriaField;
        String customer;
        String team;

        public MasterApproverParameter(
            SObject sObj,
            String amountField,
            String addCriteriaField,
            String customer,
            String team
        ) {
            this.sObj = sObj;
            this.amountField = amountField;
            this.addCriteriaField = addCriteriaField;
            this.customer = customer;
            this.team = team;
        }
    }
}