@RestResource(urlMapping='/NFM108/*')
global with sharing class NFM108Rest {
	global class PaymentRest{
       public Payment Payment;
    }
	global class Payment {
        public NFMUtil.Monitoring Monitoring;
        public GeneralData[] GeneralData;
    }
    global class GeneralData {
        public String SFDCRepairNo;
        public String PaymentSource;
        public String PaymentAmount;
        public String PaymentDate;
        public String AccumulativeTotalPaymentAmount;
        public String ArrearsBasePaymentTerm;
        public String ARAmountBasePaymentTerm;
        public String ArrearsBaseInvoice;
        public String ARAmountBaseInvoice;
        public String ARAmountBaseAverage;
        public String AccumulativeARAmountBaseAverage;
        public String BaddebtsFlg;
    }

    private class ExtraData {
        public GeneralData iData;
        public String SFDCRepairNo;
        public String PaymentVoucher;
        public ExtraData(GeneralData gData) {
            this.iData = gData;
            this.SFDCRepairNo = gData.SFDCRepairNo;
            if (!(gData.SFDCRepairNo == null || gData.SFDCRepairNo == '')) {
                List<String> splitSFDCRepairNo = gData.SFDCRepairNo.split(':');
                this.SFDCRepairNo = splitSFDCRepairNo[0];
                if (splitSFDCRepairNo.size() > 1) {
                    this.PaymentVoucher = splitSFDCRepairNo[1];
                }
            }
        }
    }

    @HttpPost
    global static void execute() {
    	String strData = RestContext.request.requestBody.toString();
    	PaymentRest paymentRest = (PaymentRest) JSON.deserializeStrict(strData, PaymentRest.class);

        if (paymentRest == null ) {
            return;
        }

        NFMUtil.Monitoring Monitoring = paymentRest.payment.Monitoring;
        if (Monitoring == null) {
            return;
        }

        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'NFM108', paymentRest.Payment.GeneralData);
        if (String.isBlank(rowData.Log__c) == false) executefuture(rowData.Id);


    }

    @future
    global static void executefuture(String rowData_Id) {
        main(rowData_Id);
    }

    global static void main(String rowData_Id) {
    	Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt);
        BatchIF_Log__c rowData = [Select Id, Name, Log__c, ErrorLog__c, Log2__c, Log3__c, Log4__c, Log5__c, Log6__c, Log7__c, Log8__c, Log9__c, Log10__c, Log11__c, Log12__c, MessageGroupNumber__c, TransmissionDateTime__c,retry_cnt__c from BatchIF_Log__c where RowDataFlg__c = true and Id = :rowData_Id];
        String logstr = rowData.MessageGroupNumber__c + ' start\n';
        BatchIF_Log__c iflog = new BatchIF_Log__c();
        iflog.Type__c = 'NFM108';
        iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
        iflog.Log__c = logstr;
        iflog.ErrorLog__c = '';
        insert iflog;
        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        List<GeneralData> generalDataList = (List<GeneralData>) JSON.deserialize(rowDataStr, List<GeneralData>.class);
        if (generalDataList == null || generalDataList.size() == 0) {
            return;
        }
        Savepoint sp = Database.setSavepoint();
        try {
            List<String> receiptNoList = new List<String>();
            List<String> mcManagementCodeList = new List<String>();
            List<ExtraData> gDataList = new List<ExtraData>();
            for (GeneralData iData : generalDataList) {
                ExtraData gData = new ExtraData(iData);
                gDataList.add(gData);
                if (iData.SFDCRepairNo == null || iData.SFDCRepairNo == '') continue;
                if (iData.PaymentSource == '维修单')
                    receiptNoList.add(gData.SFDCRepairNo);
                else if (iData.PaymentSource == '维修合同')
                    mcManagementCodeList.add(gData.SFDCRepairNo);
                else continue;
            }

            Map<String, Repair__c> recptsMap = new Map<String, Repair__c>();
            for (Repair__c recpt : [
                    Select Id, Name, NFM108_Receipt__r.MessageGroupNumber__c, Received_Date__c, BaddebtsDate__c from Repair__c where Name IN :receiptNoList
            ]) {
                recptsMap.put(recpt.Name, recpt);
            }

            Map<String, Maintenance_Contract__c> mcMap = new Map<String, Maintenance_Contract__c>();
            for (Maintenance_Contract__c mc : [
                    Select Id, Maintenance_Contract_No__c, NFM108_Receipt__r.MessageGroupNumber__c, Received_Date__c, BaddebtsDate__c from Maintenance_Contract__c where Maintenance_Contract_No__c IN :mcManagementCodeList
            ]) {
                mcMap.put(mc.Maintenance_Contract_No__c, mc);
            }

            Map<String, Repair_receipt__c> receiptLastMap = new Map<String, Repair_receipt__c>();
            Map<String, Repair_receipt__c> receiptUniqueMap = new Map<String, Repair_receipt__c>();
            for (ExtraData gData : gDataList) {
                if (gData.SFDCRepairNo == null || gData.SFDCRepairNo == '') {
                    iflog.ErrorLog__c += 'SFDCRepairNo[' + gData.SFDCRepairNo + ']Required\n';
                    continue;
                }
                if (gData.iData.PaymentSource == '维修单') {
                    Repair__c rpr = recptsMap.get(gData.SFDCRepairNo);
                    if (rpr == null) {
                        iflog.ErrorLog__c += '修理[' + gData.SFDCRepairNo + ']NotExist\n';
                        continue;
                    }
                    logstr += '修理:' + gData.SFDCRepairNo + ' ';
                    Repair_receipt__c rr = new Repair_receipt__c(
                            Name = gData.iData.SFDCRepairNo,
                            UniqueKey__c = gData.iData.SFDCRepairNo,
                            Repair__c = rpr.Id,
                            Maintenance_Contract__c = System.Label.Olympus_Dummy_MC,
                            SFDCRepairNo__c = gData.SFDCRepairNo,
                            PaymentVoucher__c = gData.PaymentVoucher,
                            AccumulativeTotalPaymentAmount__c = String.isBlank(gData.iData.AccumulativeTotalPaymentAmount) ? null : Decimal.valueOf(gData.iData.AccumulativeTotalPaymentAmount),
                            ArrearsBasePaymentTerm__c = String.isBlank(gData.iData.ArrearsBasePaymentTerm) ? null : Decimal.valueOf(gData.iData.ArrearsBasePaymentTerm),
                            ARAmountBasePaymentTerm__c = String.isBlank(gData.iData.ARAmountBasePaymentTerm) ? null : Decimal.valueOf(gData.iData.ARAmountBasePaymentTerm),
                            ArrearsBaseInvoice__c = String.isBlank(gData.iData.ArrearsBaseInvoice) ? null : Decimal.valueOf(gData.iData.ArrearsBaseInvoice),
                            ARAmountBaseInvoice__c = String.isBlank(gData.iData.ARAmountBaseInvoice) ? null : Decimal.valueOf(gData.iData.ARAmountBaseInvoice),
                            ARAmountBaseAverage__c = String.isBlank(gData.iData.ARAmountBaseAverage) ? null : Decimal.valueOf(gData.iData.ARAmountBaseAverage),
                            AccumulativeARAmountBaseAverage__c = String.isBlank(gData.iData.AccumulativeARAmountBaseAverage) ? null : Decimal.valueOf(gData.iData.AccumulativeARAmountBaseAverage),
                            BaddebtsFlg__c = gData.iData.BaddebtsFlg,
                            MessageGroupNumber__c = rowData.MessageGroupNumber__c
                    );
                    if (gData.iData.BaddebtsFlg == 'X') {
                        rr.BaddebtsAmount__c = String.isBlank(gData.iData.PaymentAmount) ? null : Decimal.valueOf(gData.iData.PaymentAmount);
                        rr.BaddebtsDate__c = NFMUtil.parseStr2Date(gData.iData.PaymentDate);
                    } else {
                        rr.PaymentAmount__c = String.isBlank(gData.iData.PaymentAmount) ? null : Decimal.valueOf(gData.iData.PaymentAmount);
                        rr.PaymentDate__c = NFMUtil.parseStr2Date(gData.iData.PaymentDate);
                    }
                    receiptUniqueMap.put(gData.iData.SFDCRepairNo, rr);
                    receiptLastMap.put(rpr.Id, rr);
                }
                else if (gData.iData.PaymentSource == '维修合同' || gData.iData.PaymentSource == ' 维修合同') {
                    Maintenance_Contract__c mc = mcMap.get(gData.SFDCRepairNo);
                    if (mc == null) {
                        iflog.ErrorLog__c += '维修合同[' + gData.SFDCRepairNo + ']NotExist\n';
                        continue;
                    }
                    logstr += '维修合同:' + gData.SFDCRepairNo + ' ';
                    Repair_receipt__c rr = new Repair_receipt__c(
                            Name = gData.iData.SFDCRepairNo,
                            UniqueKey__c = gData.iData.SFDCRepairNo,
                            Repair__c = System.Label.Olympus_Dummy_Repair,
                            Maintenance_Contract__c = mc.Id,
                            SFDCRepairNo__c = gData.SFDCRepairNo,
                            PaymentVoucher__c = gData.PaymentVoucher,
                            AccumulativeTotalPaymentAmount__c = String.isBlank(gData.iData.AccumulativeTotalPaymentAmount) ? null : Decimal.valueOf(gData.iData.AccumulativeTotalPaymentAmount),
                            ArrearsBasePaymentTerm__c = String.isBlank(gData.iData.ArrearsBasePaymentTerm) ? null : Decimal.valueOf(gData.iData.ArrearsBasePaymentTerm),
                            ARAmountBasePaymentTerm__c = String.isBlank(gData.iData.ARAmountBasePaymentTerm) ? null : Decimal.valueOf(gData.iData.ARAmountBasePaymentTerm),
                            ArrearsBaseInvoice__c = String.isBlank(gData.iData.ArrearsBaseInvoice) ? null : Decimal.valueOf(gData.iData.ArrearsBaseInvoice),
                            ARAmountBaseInvoice__c = String.isBlank(gData.iData.ARAmountBaseInvoice) ? null : Decimal.valueOf(gData.iData.ARAmountBaseInvoice),
                            ARAmountBaseAverage__c = String.isBlank(gData.iData.ARAmountBaseAverage) ? null : Decimal.valueOf(gData.iData.ARAmountBaseAverage),
                            AccumulativeARAmountBaseAverage__c = String.isBlank(gData.iData.AccumulativeARAmountBaseAverage) ? null : Decimal.valueOf(gData.iData.AccumulativeARAmountBaseAverage),
                            BaddebtsFlg__c = gData.iData.BaddebtsFlg,
                            MessageGroupNumber__c = rowData.MessageGroupNumber__c
                    );
                    if (gData.iData.BaddebtsFlg == 'X') {
                        rr.BaddebtsAmount__c = String.isBlank(gData.iData.PaymentAmount) ? null : Decimal.valueOf(gData.iData.PaymentAmount);
                        rr.BaddebtsDate__c = NFMUtil.parseStr2Date(gData.iData.PaymentDate);
                    } else {
                        rr.PaymentAmount__c = String.isBlank(gData.iData.PaymentAmount) ? null : Decimal.valueOf(gData.iData.PaymentAmount);
                        rr.PaymentDate__c = NFMUtil.parseStr2Date(gData.iData.PaymentDate);
                    }
                    receiptUniqueMap.put(gData.iData.SFDCRepairNo, rr);
                    receiptLastMap.put(mc.Id, rr);
                }
                else {
                    iflog.ErrorLog__c += 'SFDCRepairNo[' + gData.SFDCRepairNo + ']' + gData.iData.PaymentSource + ':Undefined\n';
                    continue;
                }
            }
            if (receiptUniqueMap.size() > 0) {
                upsert receiptUniqueMap.values() UniqueKey__c;
            }
            // 親の更新
            List<Repair__c> rprList = new List<Repair__c>();
            List<Maintenance_Contract__c> mcList = new List<Maintenance_Contract__c>();
            for (Repair_receipt__c receipt : receiptLastMap.values()) {
                Repair__c rpr = recptsMap.get(receipt.SFDCRepairNo__c);
                Maintenance_Contract__c mc = mcMap.get(receipt.SFDCRepairNo__c);
                if (rpr != null) {
                    if (String.isBlank(rpr.NFM108_Receipt__r.MessageGroupNumber__c) || Integer.valueOf(rpr.NFM108_Receipt__r.MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                        rpr.NFM108_Receipt__c = receipt.Id;
                        rpr.Paid_Amount__c = receipt.AccumulativeTotalPaymentAmount__c;
                        rpr.Unpaid_Amount_ESAS__c = receipt.ArrearsBaseInvoice__c;
                        rpr.Unpaid_amount_IF__c = receipt.ArrearsBasePaymentTerm__c;
                    }
                    if (receipt.ArrearsBasePaymentTerm__c == 0) {
                        //if (rpr.Received_Date__c == null) {
                            rpr.Received_Date__c = (receipt.PaymentDate__c == null) ? receipt.BaddebtsDate__c : receipt.PaymentDate__c;
                        //} 
                    } else {
                        rpr.Received_Date__c = null;
                    }
                    if (rpr.BaddebtsDate__c == null && receipt.BaddebtsFlg__c == 'X') {
                        rpr.BaddebtsDate__c = receipt.BaddebtsDate__c;
                    }
                    rprList.add(rpr);
                }
                else if (mc != null) {
                    if (String.isBlank(mc.NFM108_Receipt__r.MessageGroupNumber__c) || Integer.valueOf(mc.NFM108_Receipt__r.MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                        mc.NFM108_Receipt__c = receipt.Id;
                        mc.Recoverable_Amount__c = receipt.AccumulativeTotalPaymentAmount__c;
                        mc.Not_collect_money__c = receipt.ArrearsBaseInvoice__c;
                        mc.Total_not_collect_amount__c = receipt.ArrearsBasePaymentTerm__c;
                    }
                    if (receipt.ArrearsBasePaymentTerm__c == 0) {
                        if (mc.Received_Date__c == null) {
                            mc.Received_Date__c = (receipt.PaymentDate__c == null) ? receipt.BaddebtsDate__c : receipt.PaymentDate__c;
                        }
                    } else {
                        mc.Received_Date__c = null;
                    }
                    if (mc.BaddebtsDate__c == null && receipt.BaddebtsFlg__c == 'X') {
                        mc.BaddebtsDate__c = receipt.BaddebtsDate__c;
                    }
                    mcList.add(mc);
                }
            }
            if (rprList.size() > 0) update rprList;
            if (mcList.size() > 0) update mcList;
            logstr += '\nend';
            rowData.retry_cnt__c=0;
        } catch (Exception ex) {
            // エラーが発生した場合
            Database.rollback(sp);
            System.debug(Logginglevel.ERROR, 'NFM108_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'NFM108_' + rowData.MessageGroupNumber__c + ':' + ex.getStackTraceString());
            logstr += '\n' + ex.getMessage();
            iflog.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + iflog.ErrorLog__c;
            if (rowData.retry_cnt__c == null) rowData.retry_cnt__c = 0;
            if (rowData.retry_cnt__c < batch_retry_max_cnt){
                 rowData.retry_cnt__c++;
                 LogAutoSendSchedule.assignOneMinute();
            }
            if (rowData.retry_cnt__c >= batch_retry_max_cnt){
                rowData.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + rowData.ErrorLog__c+'错误次数已经超过自动收信设定的最大次数，请手动收信';
            }
        }
        update rowData;
        iflog.Log__c = logstr;
        if (iflog.Log__c.length() > 131072) {
            iflog.Log__c = iflog.Log__c.subString(0, 131065) + ' ...';
        }
        if (iflog.ErrorLog__c.length() > 32768) {
            iflog.ErrorLog__c = iflog.ErrorLog__c.subString(0, 32760) + ' ...';
        }
        update iflog;
    }
}