public without sharing class ApprovalHistoryController {

    public static final String APPROVE_ACTION = 'Approve';
    public static final String REJECT_ACTION = 'Reject';
    public static final String RECALL_ACTION = 'Removed';
    public class ReturnResult{
        @AuraEnabled
        public String returnMes;
        @AuraEnabled
        public Boolean success;
    }
    public class InitWrap{
        @AuraEnabled
        public String objJson;
        @AuraEnabled
        public String currentUserProfileId;
        @AuraEnabled
        public String nodeName;
    }
    @AuraEnabled
    public static InitWrap getInitData(String recordId, String objectApiName){
        InitWrap i = new InitWrap();

        List<ProcessInstanceWorkitem> workItems = [
            SELECT Id, ProcessInstanceId 
            FROM ProcessInstanceWorkitem 
            WHERE ProcessInstance.TargetObjectId = :recordId 
        ];
        if (workItems.size()>0) {
            ProcessInstance proIn = [SELECT Id,SubmittedById, ProcessDefinition.Name , (SELECT ID, ProcessNodeId,  
                                            StepStatus,Comments,TargetObjectId,ActorId,CreatedById,IsDeleted,IsPending  
                                            ,OriginalActorId,ProcessInstanceId,RemindersSent,CreatedDate, Actor.Name,
                                            OriginalActor.Name , ProcessNode.Name FROM StepsAndWorkitems order by IsPending DESC,CreatedDate DESC)   
                                            FROM ProcessInstance where Id=:workItems.get(0).ProcessInstanceId order by CreatedDate DESC];  
            String nodeName = '';
            if(proIn.StepsAndWorkitems.size()>0 && proIn !=null){
                if(String.isNotBlank(proIn.StepsAndWorkitems[0].ProcessNode.Name)){
                    nodeName = proIn.StepsAndWorkitems[0].ProcessNode.Name;
                }
            }
            i.nodeName = nodeName;
        }
        


        if(objectApiName=='Account'){
            Account acc = [select id,Name,WhetherRiskPassing__c,RejectionReason__c,AssociatedHospital__c,InstitutionalType__c,HospitalType__c from Account where id=:recordId];
            String profileId = UserInfo.getProfileId();
            acc.RejectionReason__c = '';
            acc.AssociatedHospital__c = null;
            i.objJson = JSON.serialize(acc);
            i.currentUserProfileId = profileId;
            return i;
        }else if(objectApiName=='Account_Delay_Apply__c'){
            Account_Delay_Apply__c acc = [select id,InstitutionalType__c,HospitalType__c,WhetherRiskPassing__c from Account_Delay_Apply__c where id=:recordId];
            String profileId = UserInfo.getProfileId();
            i.objJson = JSON.serialize(acc);
            i.currentUserProfileId = profileId;
            return i;
        }else if(objectApiName=='Solution_Programme__c'){
            Solution_Programme__c acc = [select id,Confirmation_Result__c,Remarks__c,Scheme_Type__c from Solution_Programme__c where id=:recordId];
            String profileId = UserInfo.getProfileId();
            i.objJson = JSON.serialize(acc);
            i.currentUserProfileId = profileId;
            return i;
        }
        return i;
    }
    @AuraEnabled
    public static String saveRecord(String objectApiName, String objId, String objJson){
        system.debug(objectApiName);
        system.debug(objId);
        system.debug(objJson);
        if(objectApiName=='Account'){
            Account acc = (Account)JSON.deserialize(objJson, Account.class);
            acc.Id = objId;
            update acc;
        }else if(objectApiName=='Account_Delay_Apply__c'){
            Account_Delay_Apply__c accApply = (Account_Delay_Apply__c)JSON.deserialize(objJson, Account_Delay_Apply__c.class);
            accApply.Id = objId;
            update accApply;
        }else if(objectApiName=='Solution_Programme__c'){
            Solution_Programme__c sol = (Solution_Programme__c)JSON.deserialize(objJson, Solution_Programme__c.class);
            sol.Id = objId;
            update sol;
        }
        return '200';
    }
    @AuraEnabled(Cacheable=true)
    public static List<LookupSearchResult> searchUsers(String searchTerm) {
        // Prepare query paramters
        searchTerm += '*';

        // Execute search query
        List<List<SObject>> searchResults = [
            FIND :searchTerm
            IN ALL FIELDS
            RETURNING
                User(Id, FirstName, LastName)
            LIMIT :ApprovalHistoryUtil.MAX_RESULTS 
        ];

        // Prepare results
        List<LookupSearchResult> results = new List<LookupSearchResult>();

        // Extract Accounts & convert them into LookupSearchResult
        String userIcon = 'standard:user';
        User[] users = (List<User>) searchResults[0];
        for (User currUser : users) {
            results.add(
                new LookupSearchResult(
                    currUser.Id,
                    'User',
                    userIcon,
                    currUser.FirstName + ' ' + currUser.LastName,
                    ''
                )
            );
        }

        // Optionnaly sort all results on title
        results.sort();

        return results;
    }

    @AuraEnabled
    public static String processStep(String recordId, String comments, String nextApproverId, String action,String objApiName,String modalsubmitLabel,String objJson){
        List<ProcessInstanceWorkitem> workItems = [
            SELECT Id, ProcessInstanceId 
            FROM ProcessInstanceWorkitem 
            WHERE ProcessInstance.TargetObjectId = :recordId 
        ];
        if(workItems.isEmpty()){
            return '';
        }
        Account obj;
        Account_Delay_Apply__c accApply;
        Solution_Programme__c sol;
        if(objApiName=='Account'){
            obj = (Account)JSON.deserialize(objJson, Account.class);
        }else if(objApiName=='Account_Delay_Apply__c'){
            accApply = (Account_Delay_Apply__c)JSON.deserialize(objJson, Account_Delay_Apply__c.class);
        }else if(objApiName=='Solution_Programme__c'){
            sol = (Solution_Programme__c)JSON.deserialize(objJson, Solution_Programme__c.class);
        }
        // List<ProcessInstanceStep> pList = [select id,StepNodeId,StepStatus from ProcessInstanceStep 
        // where ProcessInstanceId=:workItems.get(0).ProcessInstanceId];
        system.debug(workItems);
        ProcessInstance proIn = [SELECT Id,SubmittedById, ProcessDefinition.Name , (SELECT ID, ProcessNodeId,  
                                            StepStatus,Comments,TargetObjectId,ActorId,CreatedById,IsDeleted,IsPending  
                                            ,OriginalActorId,ProcessInstanceId,RemindersSent,CreatedDate, Actor.Name,
                                            OriginalActor.Name , ProcessNode.Name FROM StepsAndWorkitems order by IsPending DESC,CreatedDate DESC)   
                                            FROM ProcessInstance where Id=:workItems.get(0).ProcessInstanceId order by CreatedDate DESC];  
        String nodeName = '';
        system.debug(proIn);
        if(proIn.StepsAndWorkitems.size()>0){
            if(String.isNotBlank(proIn.StepsAndWorkitems[0].ProcessNode.Name)){
                nodeName = proIn.StepsAndWorkitems[0].ProcessNode.Name;
            }
        }
        // for(ProcessInstanceHistory step : proIn.StepsAndWorkitems){
        //     if(String.isNotBlank(step.ProcessNode.Name)){
        //         system.debug(step.ProcessNode.Name);
        //         nodeName = step.ProcessNode.Name;
        //     }
        // }
        String returnMes = '';
        system.debug('----');
        system.debug(obj);
        system.debug(accApply);
        system.debug(sol);
        system.debug(objApiName);
        system.debug(nodeName);
        system.debug(modalsubmitLabel);
        system.debug(nextApproverId);
        if(String.isNotBlank(nodeName)){
            system.debug('qqqqq');
            String testlink = nodeName;
            // obj.Id = recordId;
            if(objApiName=='Account'){
                obj.CustomizePageFlg__c = true;
                if(modalsubmitLabel == '批准' || modalsubmitLabel == '拒绝'){
                    system.debug('1');
                    Date today = Date.today();
                    // if(testlink.contains('医院新建审批_营业支援部') ){
                    if(testlink.contains('医院新建审批_事业推进部') ){
                        system.debug('1-1');
                        if(modalsubmitLabel == '批准'){
                            system.debug('1-1-1');
                            if(!String.isBlank(obj.RejectionReason__c)){
                                returnMes='您已填写驳回理由，批准不需要驳回理由。';
                            }
                            if(String.isBlank(obj.InstitutionalType__c)){
                                returnMes= '批准前，机构类型必填。';
                            }
                            if(obj.InstitutionalType__c == '非医疗机构' && String.isBlank(obj.HospitalType__c)){
                                returnMes= '非医疗机构请选择医院类型。';
                            }
                            if(obj.InstitutionalType__c == '医疗机构' && !String.isBlank(obj.HospitalType__c)){
                                returnMes= '医疗机构不需要选择医院类型。';
                            }
                            if(obj.InstitutionalType__c == '医疗机构'){
                                obj.Is_Active__c = '有効';
                                obj.Approved_Confirm_Date__c = today;
                            }
                        }
                        //拒绝
                        if(modalsubmitLabel == '拒绝'){
                            if(String.isBlank(obj.RejectionReason__c)){
                                returnMes= '拒绝前，请选择驳回理由。';
                            }
                            if(obj.RejectionReason__c == '重复' && String.isBlank(obj.AssociatedHospital__c)){
                                returnMes= '驳回理由是重复的，请填写关联医院。';
                            }
                            if(obj.RejectionReason__c != '重复' && !String.isBlank(obj.AssociatedHospital__c)){
                                returnMes= '驳回理由不是重复的，不能填写关联医院。';
                            }
                            if(!String.isBlank(obj.RejectionReason__c) && (!String.isBlank(obj.InstitutionalType__c)||!String.isBlank(obj.HospitalType__c))){
                                returnMes= '审批拒绝，不允许填写机构类型或医院类型。';
                            }
                            if(obj.RejectionReason__c == '医院已关张' || obj.RejectionReason__c == '重复'){
                                system.debug('拒绝——驳回');
                                obj.Is_Active__c = '驳回';
                            }else{
                                system.debug('拒绝——草案中');
                                obj.Is_Active__c = '草案中';
                            }
                        }
                    }else if(testlink.contains('质量法规二级部长') ){
                        system.debug('22222222222222');
                        if(modalsubmitLabel == '批准'){
                            system.debug('2-2222');
                            if(obj.InstitutionalType__c == '非医疗机构' && obj.HospitalType__c == '高等院校'){
                                system.debug('2-3333333');
                                obj.Is_Active__c = '有効';
                                obj.Approved_Confirm_Date__c = today;
                            }
                        }
                        if(modalsubmitLabel == '拒绝'){
                            obj.Is_Active__c = '驳回';
                            obj.Approved_Confirm_Date__c = today;
                        }     
                    }else if(testlink.contains('经销商管理部一级审批')){
                        if(modalsubmitLabel == '批准'){
                            if(String.isBlank(obj.WhetherRiskPassing__c)){
                                returnMes= '是否为有风险通过 必填。';
                            }else if(obj.InstitutionalType__c == '非医疗机构' && obj.HospitalType__c == '企业集团' && (obj.WhetherRiskPassing__c == '否'||String.isBlank(obj.WhetherRiskPassing__c))){
                                obj.Is_Active__c = '有効';
                                obj.Approved_Confirm_Date__c = today;
                            }
                        }
                        if(modalsubmitLabel == '拒绝'){
                            obj.Is_Active__c = '驳回';
                        } 
                    }else if(testlink.contains('总经理审批')){
                        if(modalsubmitLabel == '批准'){
                            obj.Is_Active__c = '有効';
                            obj.Approved_Confirm_Date__c = today;
                        }
                        if(modalsubmitLabel == '拒绝'){
                            obj.Is_Active__c = '驳回';
                        } 
                    }else{
                        if(modalsubmitLabel == '拒绝'){
                            obj.Is_Active__c = '驳回';
                        }   
                    }
                }
            }else if(objApiName=='Account_Delay_Apply__c'){
                system.debug('Account_Delay_Apply__c');
                accApply.CustomizePageFlg__c = true;
                if(modalsubmitLabel == '批准' || modalsubmitLabel == '拒绝'){
                    system.debug('1111');
                    if(testlink.contains('营业窗口审批')){
                        system.debug('2222');
                        if(modalsubmitLabel == '拒绝'){
                            system.debug('3333');
                            accApply.Is_Active__c = '草案中';
                        }   
                    // }else if(testlink.contains('医院新建审批_营业支援部') ){
                    }else if(testlink.contains('医院变更审批_事业推进部') ){
                        system.debug('医院变更审批_事业推进部');
                        system.debug(accApply.InstitutionalType__c);
                        system.debug(accApply.HospitalType__c);
                        if(modalsubmitLabel == '批准'){
                            if(accApply.InstitutionalType__c == null){
                                returnMes='批准前，机构类型必填。';
                            }
                            if(accApply.InstitutionalType__c == '非医疗机构' && accApply.HospitalType__c == null){
                                returnMes='非医疗机构请选择医院类型。';
                            }
                            if(accApply.InstitutionalType__c == '医疗机构' && accApply.HospitalType__c != null){
                                returnMes='医疗机构不需要选择医院类型。';
                            }
                            if(accApply.InstitutionalType__c == '医疗机构'){
                                accApply.Is_Active__c = '审批通过';
                                accApply.Approved_Confirm_Date__c = Date.today();
                            }
                        }
                        if(modalsubmitLabel == '拒绝'){
                            if(accApply.InstitutionalType__c == null){
                                returnMes='拒绝前，机构类型必填。';
                            }
                            // accApply.Is_Active__c = '草案中';
                            if(accApply.InstitutionalType__c == '医疗机构'){
                                accApply.Is_Active__c = '驳回';
                            }else if(accApply.InstitutionalType__c == '非医疗机构'){
                                accApply.Is_Active__c = '草案中';
                            }
                        }
                    }else if(testlink.contains('质量法规二级部长') ){
                        system.debug('质量法规二级部长');
                        if(modalsubmitLabel == '批准'){
                           if(accApply.InstitutionalType__c == '非医疗机构' && accApply.HospitalType__c == '高等院校'){
                              accApply.Is_Active__c = '审批通过';
                              accApply.Approved_Confirm_Date__c = Date.today();
                           }
                        }
                        if(modalsubmitLabel == '拒绝'){
                            accApply.Is_Active__c = '驳回';
                        }     
                     }else if(testlink.contains('经销商管理部一级审批')){
                        system.debug('经销商管理部一级审批');
                        if(modalsubmitLabel == '批准'){
                            if(String.isBlank(accApply.WhetherRiskPassing__c)){
                                returnMes='是否为有风险通过 必填。';
                            }
                           if(accApply.InstitutionalType__c == '非医疗机构' && accApply.HospitalType__c == '企业集团' && accApply.WhetherRiskPassing__c == '否'){
                              accApply.Is_Active__c = '审批通过';
                              accApply.Approved_Confirm_Date__c = Date.today();
                           }
                        }
                        if(modalsubmitLabel == '拒绝'){
                            accApply.Is_Active__c = '驳回';
                        } 
                    }else if(testlink.contains('总经理审批')){
                        system.debug('总经理审批');
                        if(modalsubmitLabel == '批准'){
                            accApply.Is_Active__c = '审批通过';
                            accApply.Approved_Confirm_Date__c = Date.today();
                        }
                        if(modalsubmitLabel == '拒绝'){
                            accApply.Is_Active__c = '驳回';
                        } 
                    }else{
                        system.debug('else');
                        if(modalsubmitLabel == '拒绝'){
                            accApply.Is_Active__c = '驳回';
                        }   
                    }
                }
            }else if(objApiName=='Solution_Programme__c'){
                // if(modalsubmitLabel == '批准'){
                // 	returnMes='请填写反馈结果，并按审批按钮';
                // }
                // if(sol.Confirmation_Result__c == null){
                // 	returnMes='批准之前必须填写反馈结果！';
                // }
                if(modalsubmitLabel == '拒绝'){
                    returnMes='请填写反馈结果，并按审批按钮';
                }
                if(modalsubmitLabel == '批准'&&sol.Confirmation_Result__c == null){
                	returnMes='请填写反馈结果，并按审批按钮';
                }
                // sol.ProcessOfApproval__c = false;
            }
        }
        system.debug('end');
        system.debug(returnMes);
        ReturnResult r = new ReturnResult();
        if(String.isNotBlank(returnMes)){
            r.returnMes=returnMes;
            r.success=false;
            return JSON.serialize(r);
        }
        try{
            if(objApiName=='Account'){
                update obj;
            }else if(objApiName=='Account_Delay_Apply__c'){
                update accApply;
            }else if(objApiName=='Solution_Programme__c'){
                update sol;
            }
        }catch(Exception e){
            r.returnMes=e.getMessage();
            r.success=false;
            return JSON.serialize(r);
        }
        String result = ApprovalHistoryUtil.processStep(workItems,comments, nextApproverId,action);
        system.debug('result:'+result);
        return result;
    }

    @AuraEnabled
    public static void reassignStep(String recordId, String newActorId ){
        List<ProcessInstanceWorkItem> workItemList = [SELECT ActorId FROM ProcessInstanceWorkitem WHERE ProcessInstance.TargetObjectId = : recordId];
        ApprovalHistoryUtil.reassignStep(workItemList, newActorId);
    }


    @AuraEnabled
    public static String submitForApproval(String recordId, String comments, String nextApproverId){
        Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
        req.setComments(comments);
        if(!String.isBlank(nextApproverId)){
            req.setNextApproverIds(new Id[] {nextApproverId});
        }
        req.setObjectId(recordId);
        
        // Submit on behalf of a specific submitter
        req.setSubmitterId(ApprovalHistoryUtil.currentUserId); 
        // Submit the approval request for the account
        Approval.ProcessResult result = Approval.process(req);
        
        return JSON.serialize(result);
        
    }


    @AuraEnabled (cacheable=true)
    public static ApprovalHistory getApprovalHistory(String recordId){  
                          
        List<ProcessInstance> processInstances = [SELECT Id,SubmittedById, ProcessDefinition.Name , (SELECT ID, ProcessNodeId,  
                                                            StepStatus,Comments,TargetObjectId,ActorId,CreatedById,IsDeleted,IsPending  
                                                            ,OriginalActorId,ProcessInstanceId,RemindersSent,CreatedDate, Actor.Name,  
                                                            OriginalActor.Name , ProcessNode.Name FROM StepsAndWorkitems order by IsPending DESC, CreatedDate DESC )   
                                                    FROM ProcessInstance where TargetObjectId =:recordId order by CreatedDate DESC];                                                                         
  
        return ApprovalHistoryUtil.populateApprovalHistorySteps(processInstances, recordId);                                                 
                                                                            
    }  

    public class ApprovalHistoryStep{
        @AuraEnabled  
        public String stepName {get;set;}  
        @AuraEnabled  
        public String stepUrl {get;set;}
        @AuraEnabled  
        public DateTime createdDate {get;set;}   
        @AuraEnabled  
        public String stepStatus {get;set;}  
        @AuraEnabled  
        public String assignedTo {get;set;}   
        @AuraEnabled  
        public String assignedToUrl {get;set;}
        @AuraEnabled  
        public String OriginalTo {get;set;}
        @AuraEnabled  
        public String OriginalToUrl {get;set;}
        @AuraEnabled
        public String comments {get;set;}
        
        public ApprovalHistoryStep(
            String stepName,
            String stepId,
            DateTime createdDate, 
            String stepStatus,
            String assignedTo,
            String assignedToId,
            String comments )  
        { 
            this.stepName = stepName;
            this.stepUrl = '/' + stepId;
            this.createdDate = createdDate;
            this.assignedTo = assignedTo;  
            this.assignedToUrl = '/'+assignedToId;
            this.comments = comments;

            if(stepStatus == ApprovalHistoryUtil.STATUS_STARTED){
                this.stepStatus = ApprovalHistoryUtil.STATUS_SUBMITTED;
            }else if(stepStatus == ApprovalHistoryUtil.STATUS_REMOVED){
                this.stepStatus = ApprovalHistoryUtil.STATUS_RECALLED;
            }else{
                this.stepStatus = stepStatus;
            }
            
        }
        public ApprovalHistoryStep(
            String stepName,
            String stepId,
            DateTime createdDate, 
            String stepStatus,
            String assignedTo,
            String assignedToId,
            String OriginalTo,
            String OriginalToId,
            String comments )  
        { 
            this.stepName = stepName;
            this.stepUrl = '/' + stepId;
            this.createdDate = createdDate;
            this.assignedTo = assignedTo;  
            this.assignedToUrl = '/'+assignedToId;
            this.OriginalTo = OriginalTo;  
            this.OriginalToUrl = '/'+OriginalToId;
            this.comments = comments;

            if(stepStatus == ApprovalHistoryUtil.STATUS_STARTED){
                this.stepStatus = ApprovalHistoryUtil.STATUS_SUBMITTED;
            }else if(stepStatus == ApprovalHistoryUtil.STATUS_REMOVED){
                this.stepStatus = ApprovalHistoryUtil.STATUS_RECALLED;
            }else{
                this.stepStatus = stepStatus;
            }
            
        } 
    }

    public class ApprovalHistory{
        @AuraEnabled
        public List<ApprovalHistoryStep> approvalSteps;
        @AuraEnabled
        public String approvalStepsSize;
        @AuraEnabled 
        public boolean isCurrentUserApprover; 
        @AuraEnabled 
        public boolean showRecall;  //Modify All Data" permission or "Modify All" on the object level
                                    // system admin and submitter(if it says so on the approval process)
                                        //SELECT Name FROM Profile WHERE PermissionsModifyAllData = true
                                    //query permission sets with modify all or modify all for object and see if curr user has them

        @AuraEnabled 
        public boolean showSubmitForApproval; 
        public ApprovalHistory(List<ApprovalHistoryStep> approvalSteps, boolean isCurrentUserApprover, boolean isSubmitForApproval, boolean showRecall){
            this.approvalSteps = approvalSteps;
            this.isCurrentUserApprover = isCurrentUserApprover; 
            //this.approvalStepsSize = moreThan6Steps ? '6+' : string.valueOf(approvalSteps.size());
            this.showSubmitForApproval = isSubmitForApproval;
            this.showRecall = showRecall;
        }
    }
}