/**************************************************************************************************
@Author: Denny陈帮才
@Name: EquipmentRepairBatch
@CreateDate: 22/08/2022
@Description: 过去三年维修实绩
@Version 1.0
*****************************************************************************************************/
global class EquipmentRepairBatch implements Database.Batchable<sObject>,Database.Stateful {
    public String query;
    // public List < String > accountIdList;
    public Set < String > accountIdList;

    private BatchIF_Log__c iflog;
    public Date td = Date.today();  //如2022.10.15
    public String OCSM_Period_half;
    public String OCSM_Period;
    public Date eTime=td.toStartOfMonth(); //如 2022.10.1
    public Date sTime=eTime.addYears(-3);  // 2019.10.1
    public Date egdTime = Date.newInstance(td.year()+1,3,31);


    global EquipmentRepairBatch() {
        this.query = query;
        // OCSM_Period = 'FY'+(td.year()+1);
    }

    global EquipmentRepairBatch(Set <String> accountIdList) {
        this.query = query;
        this.accountIdList = accountIdList;
        // OCSM_Period = 'FY'+(td.year()+1);
    }

    global Database.QueryLocator start(Database.BatchableContext bc) {
        system.debug('执行start');
        iflog = new BatchIF_Log__c();
        iflog.Type__c = 'PushNotification';
        iflog.Log__c  = 'EquipmentRepairBatch start\n';
        iflog.ErrorLog__c = '';
        insert iflog;
        if (td.month() >= 4 && td.month() <= 9) {
            OCSM_Period_half = '1H';
        }else{
            OCSM_Period_half = '2H';
        }

        if(td.month() >= 1 && td.month() <= 3){
            OCSM_Period = 'FY'+(td.year());
        }else{
            OCSM_Period = 'FY'+(td.year()+1);
        }

        // if(td.month() >= 4){
        //     sTime = Date.newInstance(td.year()-3,4,1);
        //     eTime = Date.newInstance(td.year(),3,31);
            
        // }else{
        //     sTime = Date.newInstance(td.year()-4,4,1);
        //     eTime = Date.newInstance(td.year()-1,3,31);
        // }
        // query ='select Id,Hospital__c,Product2.ServiceCategory__c from Asset where Id not in (Select Asset__c from Maintenance_Contract_Asset__c) and Id in (select Delivered_Product__c from Repair__c)';//没有维修合同的数据
        // query += 'and IF_Coverage_Target_Asset_F__c=1';
        //不再查询是否有维修合同
        // query ='select Id,Hospital__c,Product2.ServiceCategory__c,Product2.Maintenance_Price_Year__c from Asset where IF_Coverage_Target_Asset_F__c=1';

        //2022/12/28 修改筛选条件 同步kpi设备
        query ='select Id from Account where Id IN( select Hospital__c from Asset where IF_Coverage_Target_Asset__c=\'1\')';
       
        // query ='select Id from Account where Id IN( select Hospital__c from Asset where  '
        //                                     +' Product2.ServiceCategory__c != null '
        //                                     +' AND OwnershipMachine_No__c!=\'A22004A\' AND OwnershipMachine_No__c!=\'A37026A\' AND OwnershipMachine_No__c!=\'A4676A\' AND OwnershipMachine_No__c!=\'WA02946A\''
        //                                     +' AND Hospital__r.IF_Coverage_Target_HP__c = \'1\''
        //                                     +' AND (Product2.Maintenance_Price_Year__c != 0  and Product2.Maintenance_Price_Year__c != null)'
        //                                     +' AND (Status = \'使用中\' or Status = \'未使用\' or Status = \'不明\')' 
        //                                     +' AND (IF_StopParts_production__c != \'1\' or Product2.PartSupplyFinishDate__c = null)'
        //                                     +' AND (SerMarGuranteeType__c = null' 
        //                                     +' OR (SerMarGuranteeType__c!=null AND Guarantee_period_for_products__c < :egdTime))'
        //                                     +' )';

        // query +='and Is_Has_Contract_History__c = null';

        if (accountIdList != null && accountIdList.size() > 0) {
            query += ' AND Id IN :accountIdList ';
        }  
        System.debug(LoggingLevel.INFO, '*** query: ' + query);
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, list<Account> resultList) {
        system.debug('*** 执行execute');
        System.debug(LoggingLevel.INFO, '*** 查询IF_Coverage_Target_Asset_F__c=1的保有设备Id JSON resultList: ' + JSON.Serialize(resultList));

        //查询是否有维修合同 类型 分别统计维修金额
        //保有设备 1.有无维修合同（字段）2.

        //保有设备Id
        // List<Id> mids = new List<Id>();
        Set<Id> mids = new Set<Id>();

        //医院Id
        // List<Id> assetHos = new List<Id>();
        Set<Id> assetHos = new Set<Id>();

        // for (Asset ass: resultList) {
        //     mids.add(ass.Id);
        //     assetHos.add(ass.Hospital__c);
        // }

        //保有设备 
        List<Asset> AssetUpdate = new List<Asset>();
        for (Account acc :resultList) {
            assetHos.add(acc.Id);
            // for (Asset ass : acc.Asset_Hospital__r) {
            //     if(!mids.contains(ass.Id) ){
            //         AssetUpdate.add(ass);
            //         mids.add(ass.Id);
            //     }
            // }
        }
        for (Asset ass :[SELECT Id,Hospital__c,Product2.ServiceCategory__c,Product2.Maintenance_Price_Year__c 
                         FROM Asset WHERE IF_Coverage_Target_Asset__c='1' 
                         AND Hospital__c IN:assetHos
                         // AND Product2.ServiceCategory__c != null 
                         // AND OwnershipMachine_No__c!='A22004A' AND OwnershipMachine_No__c!='A37026A' AND OwnershipMachine_No__c!='A4676A' AND OwnershipMachine_No__c!='WA02946A'
                         // AND Hospital__r.IF_Coverage_Target_HP__c = '1'
                         // AND (Product2.Maintenance_Price_Year__c != 0  and Product2.Maintenance_Price_Year__c != null)
                         // AND (Status = '使用中' or Status = '未使用' or Status = '不明') 
                         // AND (IF_StopParts_production__c != '1' or Product2.PartSupplyFinishDate__c = null)
                         // AND (SerMarGuranteeType__c = null OR (SerMarGuranteeType__c!=null AND Guarantee_period_for_products__c <:egdTime))
                         ] ) {
            AssetUpdate.add(ass);
            mids.add(ass.Id);
        }

        System.debug(LoggingLevel.INFO, '*** mids: ' + mids);

        //保有设备、维修合同Map 1.存所有执行中的合同Id 2.存记录类型是服务合同以及维修合同的Id
        Map<Id,Id> assetMcaIdall = new Map<Id,Id>();
        Map<Id,Id> assetMcaId = new Map<Id,Id>();
        // List<Id> iditem = new List<Id>();
        //查询执行中的合同（三种类型记录类型都需要统计）
        // for (Maintenance_Contract_Asset__c mcas : [SELECT Id, Maintenance_Contract__c,Asset__c FROM Maintenance_Contract_Asset__c 
        //                                            WHERE Asset__c IN :mids
        //                                            AND Maintenance_Contract__r.Status__c = '契約' ]) {
        //     assetMcaIdall.put(mcas.Asset__c, mcas.Maintenance_Contract__c);
        //     // iditem.add(mcas.Id);
        // }

        //查询维修合同记录类型是服务合同以及服务类型的 维修合同Id 更新字段（是否有签约历史）
        for (Maintenance_Contract_Asset__c mcas : [SELECT Maintenance_Contract__c,Asset__c FROM Maintenance_Contract_Asset__c 
                                                   WHERE (Maintenance_Contract__r.RecordType.Name  ='服务合同' OR Maintenance_Contract__r.RecordType.Name ='维修合同')
                                                   AND Asset__c IN :mids]) {
            assetMcaId.put(mcas.Asset__c, mcas.Maintenance_Contract__c);
        }

        //查询服务目标客户
        Map<String,Account_Service_Of_Target__c> targetMap = new Map<String,Account_Service_Of_Target__c>();
        for(Account_Service_Of_Target__c asotList:[SELECT Id ,Account_HP__c,OCSM_Period_half__c,Three_Years_Repair_Cost_Soft_Mirror__c,Three_Years_Repair_Cost_Text__c,Three_Years_Repair_Cost_Surrounding_Area__c,Three_Years_Repair_Cost_Hard_Mirror__c 
                                                FROM Account_Service_Of_Target__c 
                                                WHERE OCSM_Period_half__c = :OCSM_Period_half 
                                                AND OCSM_Period__c = :OCSM_Period
                                                AND Account_HP__c IN:assetHos]){
            targetMap.put(asotList.Account_HP__c,asotList);
        }


        //存客户服务目标对象 医院Id 后续判断 有则给Id赋值。
        // Map<Id,Account_Service_Of_Target__c> hospMap = new Map<Id,Account_Service_Of_Target__c>();
        // for (Account_Service_Of_Target__c ast : asotList) {
        //     hospMap.put(ast.Account_HP__c,ast);
        // }

        //最后upsert客户服务目标对象 list目标
        List<Account_Service_Of_Target__c> asslist = new List<Account_Service_Of_Target__c>();
        //保有设备为单位 过去三年维修实绩
        Map<Id,Decimal> ThreeYearPriceSumMap = new Map<Id,Decimal>();

        //过去三年维修实际 2022/10/13 修改 为当前时间的上一个月最后一天 往前推三年 
        for(Repair__c rp :[SELECT Hospital__c,PurchaseOrInstallationDate__c,Repair_List_Price_formula__c,Delivered_Product__c 
                           FROM Repair__c WHERE Delivered_Product__c in:mids
                           AND Repair_List_Price_formula__c !=null 
                           AND Repair_List_Price_formula__c!=0 
                           AND Status1__c!='0.删除' 
                           AND Status1__c!='0.取消' 
                           AND Status2__c!='00.删除' 
                           AND Status2__c!='00.取消'
                           AND Agreed_Date__c >=:sTime 
                           AND Agreed_Date__c <:eTime 
                           ]){
            Date purDate = rp.PurchaseOrInstallationDate__c;
            if(purDate!=null){
                Decimal bDay = purDate.daysBetween(eTime);
                Decimal hmoney = 0;
                if(bDay < 0){
                    bDay *=-1;
                }
                //设备年龄不足三年的 按平均每天计算 再乘 365 再乘 3
                if((bDay < 365*3) && bDay>0){
                    hmoney = (rp.Repair_List_Price_formula__c / bDay) *365*3;
                }else{
                    hmoney = rp.Repair_List_Price_formula__c / 3;
                }
                if(ThreeYearPriceSumMap.containsKey(rp.Delivered_Product__c)){
                    ThreeYearPriceSumMap.put(rp.Delivered_Product__c, ThreeYearPriceSumMap.get(rp.Delivered_Product__c)+hmoney);
                }else{
                    ThreeYearPriceSumMap.put(rp.Delivered_Product__c, hmoney);
                }

            }
            
        }
        

        //修改时间为过去三个完成财年
        
        // Date LastThirdYearDate = td.addYears(-3);
        // System.debug(LoggingLevel.INFO, '*** LastThirdYearDate: ' + LastThirdYearDate);
        // List<AggregateResult> ThreeyearList = [
        //     select
        //     sum(Repair_List_Price_formula__c) SumPrice,
        //     sum(Repair_Quotation_Id__r.sales_discount__c) sales_discount,
        //     sum(Repair_Quotation_Id__r.Contract_target__c) contract_target,
        //     sum(Repair_Quotation_Id__r.Loaner_repair__c) loaner_repair,
        //     sum(Repair_Quotation_Id__r.long_term_insurance__c) long_term_insurance,
        //     sum(Repair_Quotation_Id__r.Set_discount__c) set_discount,
        //     sum(Repair_Quotation_Id__r.Servince_contract_discount_amount__c) sercince,
        //     sum(Repair_Quotation_Id__r.long_term_insurance_MD__c) long_term_insuranceMD,
        //     sum(Repair_Quotation_Id__r.Delivery_compensation__c) delivery,
        //     sum(Repair_Quotation_Id__r.Other_discount__c) other,
        //     AVG(Delivered_Product__r.Last_Years_Repair_Month__c) threeYearM,
        //     Delivered_Product__c
        //     from
        //     Repair__c
        //     where
        //     Delivered_Product__c in:mids
        //     and Agreed_Date__c != null
        //     and Agreed_Date__c <= :eTime
        //     and Agreed_Date__c >= :sTime
        //     and Repair_List_Price_formula__c!=0
        //     and Repair_List_Price_formula__c!=null
        //     and Status1__c!='0.删除' 
        //     and Status1__c!='0.取消' 
        //     and Status2__c!='00.删除' 
        //     and Status2__c!='00.取消'
        //     group by Delivered_Product__c
        // ];       
        // Map<Id, Decimal> ThreeYearPriceSumMap = new Map<id, Decimal>();
        // Map<Id, Decimal> ThiYearMonthMap = new Map<id, Decimal>();

        // System.debug(LoggingLevel.INFO, '*** ThreeyearList: ' + ThreeyearList);
        // for (AggregateResult Rpc : ThreeyearList) {
        //     id idf        = String.valueOf(Rpc.get('Delivered_Product__c'));
        //     //Decimal Defir = decimal.valueOf(Rpc.get('SumPrice')+'');
        //     Decimal threeYearM = decimal.valueOf(Rpc.get('threeYearM') + '');
        //     Decimal Defir = sumPrice1(Rpc);
        //     ThreeYearPriceSumMap.put(idf, Defir);
        //     ThiYearMonthMap.put(idf, threeYearM);
        // }


        //以医院为对象存储医院所有保有设备List
        Map<Id,List<Asset>> aMapLists =  new Map<Id,List<Asset>>(); 
         
        // for (Asset assertItem : resultList) {
        for (Asset assertItem : AssetUpdate) {


            //更新字段：执行中的合同 
            // if(assetMcaIdall.containsKey(assertItem.Id)){
            //     assertItem.Maintenance_Contract__c = assetMcaId.get(assertItem.Id);
            // }
            //更新字段:是否有签约历史
            if(assetMcaId.containsKey(assertItem.Id)){
                assertItem.Is_Has_Contract_History__c = '1';
            }else{
                assertItem.Is_Has_Contract_History__c = '0';
            }
            if(ThreeYearPriceSumMap.containsKey(assertItem.Id)){
                assertItem.Three_Years_Repair_Cost_Text__c = ThreeYearPriceSumMap.get(assertItem.Id); 
                assertItem.IF_Maintenance_Equipment__c = 'Y';          
                // bMapAsset.put(assertItem.Hospital__c,assertItem);

                //2022/12/28 修改 aMapLists移至 过去三年维修实绩map外
                // List<Asset> assetLists = new List<Asset>();
                // assetLists.add(assertItem);
                // if(aMapLists.containsKey(assertItem.Hospital__c)){
                //     List <Asset> alist = aMapLists.get(assertItem.Hospital__c);
                //     alist.add(assertItem);
                //     aMapLists.put(assertItem.Hospital__c,alist);
                // }else{
                //     aMapLists.put(assertItem.Hospital__c,assetLists);
                // }         
            }
            List<Asset> assetLists = new List<Asset>();
            assetLists.add(assertItem);
            if(aMapLists.containsKey(assertItem.Hospital__c)){
                List <Asset> alist = aMapLists.get(assertItem.Hospital__c);
                alist.add(assertItem);
                aMapLists.put(assertItem.Hospital__c,alist);
            }else{
                aMapLists.put(assertItem.Hospital__c,assetLists);
            } 

        }
        update AssetUpdate;
        System.debug(LoggingLevel.INFO, '*** updated AssetUpdate: ' + AssetUpdate);
        for (Id mapId : aMapLists.keySet()) {

            //test 软性镜总个数
            Decimal softCountall = 0;

            //过去三年平均维修实绩
            Decimal sumThreePrice = 0;

            //软、硬、周边未参保过去平均维修实际
            Decimal softE = 0;
            Decimal hardE = 0;
            Decimal periE = 0;
            
            //软、硬、周边定价合计(未参保)
            Decimal softTotalP = 0;
            Decimal hardTotalP = 0;
            Decimal periTotalP = 0;

            //软、硬、周边未参保数量
            Decimal softCount = 0;
            Decimal hardCount = 0;
            Decimal periCount = 0;

            for (Asset asset : aMapLists.get(mapId) ) {
                if(ThreeYearPriceSumMap.containsKey(asset.Id)){
                    sumThreePrice += asset.Three_Years_Repair_Cost_Text__c;
                    System.debug(LoggingLevel.INFO, '*** sumThreePrice: ' + sumThreePrice);
                }

                System.debug(LoggingLevel.INFO, '*** asset.Product2.ServiceCategory__c: ' + asset.Product2.ServiceCategory__c);
                System.debug(LoggingLevel.INFO, '*** asset.Is_Has_Contract_History__c: ' + asset.Is_Has_Contract_History__c);

                //分别统计软、硬、周边 1.定价总计  2.（未参保）过去三年平均维修实绩 3.未参保数量
                if(asset.Product2.ServiceCategory__c!=null){
                    if(asset.Product2.ServiceCategory__c == '软性镜'){
                        softCountall++;
                        if(asset.Is_Has_Contract_History__c == '0'){
                            softTotalP += asset.Product2.Maintenance_Price_Year__c;
                            softCount++;
                            if(ThreeYearPriceSumMap.containsKey(asset.Id)){
                                    softE += asset.Three_Years_Repair_Cost_Text__c;             
                            }
                        }

                    }else if(asset.Product2.ServiceCategory__c == '硬性镜'){
                        if(asset.Is_Has_Contract_History__c == '0'){
                            hardTotalP += asset.Product2.Maintenance_Price_Year__c;
                            hardCount++;
                            if(ThreeYearPriceSumMap.containsKey(asset.Id)){
                                hardE += asset.Three_Years_Repair_Cost_Text__c;               
                            }
                        }

                    }else if(asset.Product2.ServiceCategory__c == '周边'){                       
                        if(asset.Is_Has_Contract_History__c == '0'){
                            periTotalP += asset.Product2.Maintenance_Price_Year__c;
                            periCount++;
                            if(ThreeYearPriceSumMap.containsKey(asset.Id)){
                                periE += asset.Three_Years_Repair_Cost_Text__c;        
                            }
                        }
                    }
                }      
            }
            System.debug(LoggingLevel.INFO, '*** 周边未参保金额: ' + periE);
            System.debug(LoggingLevel.INFO, '*** 硬 未参保金额: ' + hardE);
            System.debug(LoggingLevel.INFO, '*** 软 未参保金额: ' + softE);

            Account_Service_Of_Target__c astItem = new Account_Service_Of_Target__c();
            if(targetMap.containsKey(mapId)){
                astItem = targetMap.get(mapId);  
            }else{
                astItem.OCSM_Period__c = OCSM_Period; 
                astItem.OCSM_Period_half__c = OCSM_Period_half;
                astItem.Account_HP__c = mapId;
            }
            astItem.Three_Years_Repair_Cost_Soft_Mirror__c = softE;
            astItem.Three_Years_Repair_Cost_Hard_Mirror__c = hardE;
            astItem.Three_Years_Repair_Cost_Surrounding_Area__c = periE;
            astItem.Three_Years_Repair_Cost_Text__c = sumThreePrice;
            astItem.Total_Pricing_Soft_Mirror__c = softTotalP;
            astItem.Total_Pricing_Hard_Mirror__c = hardTotalP;
            astItem.Total_Pricing_Lightsource__c = periTotalP;
            astItem.Uninsured_Quantity_Soft_Mirror__c = softCount;
            astItem.Uninsured_Quantity_Hard_Mirror__c = hardCount;
            astItem.Uninsured_Quantity_Lightsource__c = periCount;
            asslist.add(astItem);
            System.debug(LoggingLevel.INFO, '*** 软性镜总个数: ' + softCountall);
            System.debug(LoggingLevel.INFO, '*** 软性镜未参保个数: ' + astItem.Uninsured_Quantity_Soft_Mirror__c);
            System.debug(LoggingLevel.INFO, '*** :astItem.Three_Years_Repair_Cost_Soft_Mirror__c ' + astItem.Three_Years_Repair_Cost_Soft_Mirror__c);


        }
        // System.debug(LoggingLevel.INFO, '*** asslist: ' + asslist);
        // update resultList;
        upsert asslist;
        // update asslist;   

        System.debug(LoggingLevel.INFO, '***更新后 asslist: ' + asslist);


    }

    global void finish(Database.BatchableContext BC) {
        iflog.Log__c += '\nEquipmentRepairBatch end';
        String tmp = iflog.ErrorLog__c;
        if (tmp.length() > 65000) {
            tmp = tmp.substring(0, 65000);
            tmp += ' ...have more lines...';
            iflog.ErrorLog__c = tmp;
        }
        update iflog;

    }

    // private static Decimal sumPrice1(AggregateResult rpc) {
    //     Decimal SumPrice = Decimal.valueOf(rpc.get('SumPrice') + '');
    //     Decimal sales_discount = Decimal.valueOf((rpc.get('sales_discount') == null ? 0 : rpc.get('sales_discount')) + '') * -1;
    //     Decimal contract_target = Decimal.valueOf((rpc.get('contract_target') == null ? 0 : rpc.get('contract_target')) + '') * -1;
    //     Decimal loaner_repair = Decimal.valueOf((rpc.get('loaner_repair') == null ? 0 : rpc.get('loaner_repair')) + '') * -1;
    //     Decimal long_term_insurance = Decimal.valueOf((rpc.get('long_term_insurance') == null ? 0 : rpc.get('long_term_insurance')) + '') * -1;
    //     Decimal set_discount = Decimal.valueOf((rpc.get('set_discount') == null ? 0 : rpc.get('set_discount')) + '') * -1;
    //     Decimal sercince = Decimal.valueOf((rpc.get('sercince') == null ? 0 : rpc.get('sercince')) + '') * -1;
    //     Decimal long_term_insuranceMD = Decimal.valueOf((rpc.get('long_term_insuranceMD') == null ? 0 : rpc.get('long_term_insuranceMD')) + '') * -1;
    //     Decimal delivery = Decimal.valueOf((rpc.get('delivery') == null ? 0 : rpc.get('delivery')) + '') * -1;
    //     Decimal other = Decimal.valueOf((rpc.get('other') == null ? 0 : rpc.get('other')) + '') * -1;
    //     system.debug(rpc.get('SumPrice') + '--' + rpc.get('sales_discount') + '--' + rpc.get('contract_target') + '--' +
    //                  rpc.get('loaner_repair') + '--' + rpc.get('long_term_insurance') + '--' + rpc.get('set_discount') + '--' + rpc.get('long_term_insuranceMD')
    //                  + '--' + rpc.get('delivery') + '--' + rpc.get('other') + '--');
    //     return SumPrice + sales_discount + contract_target + loaner_repair + long_term_insurance + sercince + set_discount + long_term_insuranceMD + delivery + other;
    // }


}