@RestResource(urlMapping='/NFM107/*')
global with sharing class NFM107Rest  {
	global class InvoiceRest{
		public Invoice Invoice;
	}
    global class Invoice {
        public NFMUtil.Monitoring Monitoring;
        public GeneralData[] GeneralData;
    }
    global class GeneralData {
        public String SFDCRepairNo;
        public String InvoiceResource;
        public String PayerNo;
        public String BilltoPartyNo;
        public String ReverseFlag;
        public String InvoiceAmount;
        public String AccuTotalCost;
        public String AccuTotalInvoiceAmount;
        public String GoldenTaxInvoiceNo;
        public String GoldenTaxDate;
    }

    @HttpPost
    global static void execute() {
    	String strData = RestContext.request.requestBody.toString();
    	InvoiceRest ges = (InvoiceRest) JSON.deserializeStrict(strData, InvoiceRest.class);
    	if (ges == null ) {
            return;
        }

        NFMUtil.Monitoring Monitoring = ges.Invoice.Monitoring;
        if (Monitoring == null) {
            return;
        }

        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'NFM107', ges.Invoice.GeneralData);
        if (String.isBlank(rowData.Log__c) == false) {
            executefuture(rowData.Id);
        }

        // JSONを戻す
        RestResponse res = RestContext.response;
        res.addHeader('Content-Type', 'application/json');
        res.statusCode = 200;
        //String jsonResponse = '{"status": "Success", "Message":'  + gedata + '}';
        String jsonResponse = '{"status": "Success", "Message":""}';
        res.responseBody = blob.valueOf(jsonResponse);
        return;
    }

    @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,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 = 'NFM107';
        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 {
            // 更新対応配列とMapなどをセット
            List<String> accManagementCodeList = new List<String>();
            List<String> receiptNoList = new List<String>();
            List<String> mcManagementCodeList = new List<String>();
            for (NFM107Rest.GeneralData iData : generalDataList) {
                if (String.isBlank(iData.SFDCRepairNo)
                        || String.isBlank(iData.GoldenTaxInvoiceNo)
                )  continue;
                if (iData.InvoiceResource == '维修单')
                    receiptNoList.add(iData.SFDCRepairNo);
                else if (iData.InvoiceResource == '维修合同')
                    mcManagementCodeList.add(iData.SFDCRepairNo);
                else if (iData.InvoiceResource == '维修成本')
                    receiptNoList.add(iData.SFDCRepairNo);
                else continue;
                
                if (String.isBlank(iData.PayerNo) == false) {
                    accManagementCodeList.add(iData.PayerNo);
                    accManagementCodeList.add(NFMUtil.trimLeft(iData.PayerNo, '0'));
                }
                if (String.isBlank(iData.BilltoPartyNo) == false) {
                    accManagementCodeList.add(iData.BilltoPartyNo);
                    accManagementCodeList.add(NFMUtil.trimLeft(iData.BilltoPartyNo, '0'));
                }
            }

            Map<String, Repair__c> recptsMap = new Map<String, Repair__c>();
            Map<Id, Repair__c> recptsUpdMap = new Map<Id, Repair__c>();
            for (Repair__c recpt : [
                    Select Id, Name, Billing_Amount__c, NFM107_MessageGroupNumber__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>();
            Map<Id, Maintenance_Contract__c> mcUpdMap = new Map<Id, Maintenance_Contract__c>();
            for (Maintenance_Contract__c mc : [
                    Select Id, Maintenance_Contract_No__c, Invoice_amount__c, NFM107_MessageGroupNumber__c from Maintenance_Contract__c where Maintenance_Contract_No__c IN :mcManagementCodeList
            ]) {
                mcMap.put(mc.Maintenance_Contract_No__c, mc);
            }
            
            // 検索して顧客名を取得
            Map<String, Account> accManagementCodeMap = new Map<String, Account>();
            if (accManagementCodeList.size() > 0) {
                for (Account acc : [select Id, Management_Code__c, Name from Account where Management_Code__c in :accManagementCodeList]) {
                    accManagementCodeMap.put(acc.Management_Code__c, acc);
                }
            }

            Map<String, Repair_receipt__c> receiptMap = new Map<String, Repair_receipt__c>();
            for (NFM107Rest.GeneralData iData : generalDataList) {
                if (String.isBlank(iData.SFDCRepairNo)
                        || String.isBlank(iData.GoldenTaxInvoiceNo)
                ) {
                    iflog.ErrorLog__c += 'GoldenTaxInvoiceNo[' + iData.GoldenTaxInvoiceNo + '], SFDCRepairNo[' + iData.SFDCRepairNo + ']Required\n';
                    continue;
                }
                // ManagementCodeから顧客名を取得
                String payerId = null;
                String billtoPartyId = null;
                if (String.isBlank(iData.PayerNo) == false) {
                    if (accManagementCodeMap.containsKey(iData.PayerNo)) {
                        payerId = accManagementCodeMap.get(iData.PayerNo).Id;
                    } else if (accManagementCodeMap.containsKey(NFMUtil.trimLeft(iData.PayerNo, '0'))) {
                        payerId = accManagementCodeMap.get(NFMUtil.trimLeft(iData.PayerNo, '0')).Id;
                    } else {
                        iflog.ErrorLog__c += iData.GoldenTaxInvoiceNo + ':PayerNo[' + iData.PayerNo + ']NotExist\n';
                    }
                }
                if (String.isBlank(iData.BilltoPartyNo) == false) {
                    if (accManagementCodeMap.containsKey(iData.BilltoPartyNo)) {
                        billtoPartyId = accManagementCodeMap.get(iData.BilltoPartyNo).Id;
                    } else if (accManagementCodeMap.containsKey(NFMUtil.trimLeft(iData.BilltoPartyNo, '0'))) {
                        billtoPartyId = accManagementCodeMap.get(NFMUtil.trimLeft(iData.BilltoPartyNo, '0')).Id;
                    } else {
                        iflog.ErrorLog__c += iData.GoldenTaxInvoiceNo + ':BilltoPartyNo[' + iData.BilltoPartyNo + ']NotExist\n';
                    }
                }
                
                Decimal accuTotalInvoiceAmount = String.isBlank(iData.AccuTotalInvoiceAmount) ? null : Decimal.valueOf(iData.AccuTotalInvoiceAmount);
                if (iData.InvoiceResource == '维修单') {
                    Repair__c rpr = recptsMap.get(iData.SFDCRepairNo);
                    if (rpr == null) {
                        iflog.ErrorLog__c += 'GoldenTaxInvoiceNo[' + iData.GoldenTaxInvoiceNo + '], 修理[' + iData.SFDCRepairNo + ']NotExist\n';
                        continue;
                    }
                    logstr += iData.SFDCRepairNo + ':' + iData.GoldenTaxInvoiceNo + ' ';
                    if (rpr.Billing_Amount__c != accuTotalInvoiceAmount) {
                        if (String.isBlank(rpr.NFM107_MessageGroupNumber__c)
                                || Integer.valueOf(rpr.NFM107_MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                            rpr.Billing_Amount__c = accuTotalInvoiceAmount;
                            rpr.Invoice_Date__c = NFMUtil.parseStr2Date(iData.GoldenTaxDate);
                            recptsUpdMap.put(rpr.Id, rpr);
                        }
                    }
                    receiptMap.put(rpr.Id + ':' + iData.GoldenTaxInvoiceNo,
                        new Repair_receipt__c(
                            Name = iData.GoldenTaxInvoiceNo,
                            UniqueKey__c = rpr.Id + ':' + iData.GoldenTaxInvoiceNo,
                            Repair__c = rpr.Id,
                            Maintenance_Contract__c = System.Label.Olympus_Dummy_MC,
                            SFDCRepairNo__c = iData.SFDCRepairNo,
                            PayerNo__c = iData.PayerNo,
                            BilltoPartyNo__c = iData.BilltoPartyNo,
                            PayerNoAccount__c = payerId,
                            BilltoPartyNoAccount__c = billtoPartyId,
                            ReverseFlag__c = iData.ReverseFlag == 'X' ? true : false,
                            InvoiceAmount__c = String.isBlank(iData.InvoiceAmount) ? null : Decimal.valueOf(iData.InvoiceAmount),
                            AccuTotalCost__c = String.isBlank(iData.AccuTotalCost) ? null : Decimal.valueOf(iData.AccuTotalCost),
                            AccuTotalInvoiceAmount__c = accuTotalInvoiceAmount,
                            GoldenTaxDate__c = NFMUtil.parseStr2Date(iData.GoldenTaxDate),
                            MessageGroupNumber__c = rowData.MessageGroupNumber__c
                        )
                    );
                }
                else if (iData.InvoiceResource == '维修合同' || iData.InvoiceResource == ' 维修合同') {
                    Maintenance_Contract__c mc = mcMap.get(iData.SFDCRepairNo);
                    if (mc == null) {
                        iflog.ErrorLog__c += 'GoldenTaxInvoiceNo[' + iData.GoldenTaxInvoiceNo + '], 维修合同[' + iData.SFDCRepairNo + ']NotExist\n';
                        continue;
                    }
                    logstr += iData.SFDCRepairNo + ':' + iData.GoldenTaxInvoiceNo + ' ';
                    if (mc.Invoice_amount__c != accuTotalInvoiceAmount) {
                        if (String.isBlank(mc.NFM107_MessageGroupNumber__c)
                                || Integer.valueOf(mc.NFM107_MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                            mc.Invoice_amount__c = accuTotalInvoiceAmount;
                            mc.Receipt_Date__c = NFMUtil.parseStr2Date(iData.GoldenTaxDate);
                            mcUpdMap.put(mc.Id, mc);
                        }
                    }
                    receiptMap.put(mc.Id + ':' + iData.GoldenTaxInvoiceNo,
                        new Repair_receipt__c(
                            Name = iData.GoldenTaxInvoiceNo,
                            UniqueKey__c = mc.Id + ':' + iData.GoldenTaxInvoiceNo,
                            Repair__c = System.Label.Olympus_Dummy_Repair,
                            Maintenance_Contract__c = mc.Id,
                            SFDCRepairNo__c = iData.SFDCRepairNo,
                            PayerNo__c = iData.PayerNo,
                            BilltoPartyNo__c = iData.BilltoPartyNo,
                            PayerNoAccount__c = payerId,
                            BilltoPartyNoAccount__c = billtoPartyId,
                            ReverseFlag__c = iData.ReverseFlag == 'X' ? true : false,
                            InvoiceAmount__c = String.isBlank(iData.InvoiceAmount) ? null : Decimal.valueOf(iData.InvoiceAmount),
                            AccuTotalCost__c = String.isBlank(iData.AccuTotalCost) ? null : Decimal.valueOf(iData.AccuTotalCost),
                            AccuTotalInvoiceAmount__c = accuTotalInvoiceAmount,
                            GoldenTaxDate__c = NFMUtil.parseStr2Date(iData.GoldenTaxDate),
                            MessageGroupNumber__c = rowData.MessageGroupNumber__c
                        )
                    );
                }
                else if (iData.InvoiceResource == '维修成本') {
                    Repair__c rpr = recptsMap.get(iData.SFDCRepairNo);
                    if (rpr == null) {
                        iflog.ErrorLog__c += 'AccuTotalCost[' + iData.AccuTotalCost + ']GoldenTaxDate[' + iData.GoldenTaxDate + '], 修理[' + iData.SFDCRepairNo + ']NotExist\n';
                        continue;
                    }
                    logstr += iData.SFDCRepairNo + ':' + iData.AccuTotalCost + ' ' + iData.GoldenTaxDate + ' ';
                    if (String.isBlank(rpr.NFM107_MessageGroupNumber__c)
                            || Integer.valueOf(rpr.NFM107_MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                        rpr.Repair_cost__c = String.isBlank(iData.AccuTotalCost) ? null : Decimal.valueOf(iData.AccuTotalCost);
                        rpr.Repair_cost_date__c = NFMUtil.parseStr2Date(iData.GoldenTaxDate);
                        recptsUpdMap.put(rpr.Id, rpr);
                    }
                }
                else {
                    iflog.ErrorLog__c += 'SFDCRepairNo[' + iData.SFDCRepairNo + ']' + iData.InvoiceResource + ':Undefined\n';
                    continue;
                }
            }
            if (receiptMap.size() > 0) {
                upsert receiptMap.values() UniqueKey__c;
            }
            if (recptsUpdMap.size() > 0) {
                update recptsUpdMap.values();
            }
            if (mcUpdMap.size() > 0) {
                update mcUpdMap.values();
            }
            logstr += '\nend';
            rowData.retry_cnt__c=0;
        } catch (Exception ex) {
            // エラーが発生した場合
            Database.rollback(sp);
            System.debug(Logginglevel.ERROR, 'NFM107_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'NFM107_' + 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();
            } else {
                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;
    }
}