package nckd.jimin.jyyy.fi.mservice.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;

import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.util.StringUtils;
import nckd.jimin.jyyy.fi.mservice.SynSapService;
import nckd.jimin.jyyy.fi.mservice.SyncSapFIUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 同步SAP凭证
 *
 * @author turborao
 * @date 2025/5/12 19:38
 */
public class SynSapFIServiceImpl implements SynSapService {
    private static final Log logger = LogFactory.getLog(SynSapFIServiceImpl.class);


    /**
     * 同步SAP凭证
     *
     * 本方法负责从苍穹系统同步凭证到SAP凭证中
     *
     * @param  vouchsreIds 公司代码，用于过滤特定公司的项目信息
     * @return 返回一个包含同步结果的Map，包括状态码（code）和消息（msg）
     */
    @Override
    public Map<String, String> synVoucherForSap(List<Long> vouchsreIds) {
        Map<String, String> result = new HashMap<>();
        StringBuilder err = new StringBuilder();
        int count = 0;
        int errCount = 0;
        for (Long vouchsreId : vouchsreIds) {

            QFilter qf1 = new QFilter("billstatus", QCP.equals, "C");
            QFilter qf2 = new QFilter("id", QCP.equals, vouchsreId);

            String selectFields = SyncSapFIUtils.getVoucherFieldForQuery();
            DynamicObjectCollection voucherDyns = QueryServiceHelper.query("gl_voucher", selectFields, new QFilter[]{qf1, qf2});

            JSONArray ENTRY_ITEM = new JSONArray();  //凭证分录
            JSONObject HEADERITEMINFO = new JSONObject();  //凭证表头
            //现金流量项目编码 不在现金科目行上，需要单独处理下
            String maincfitemNumber = "";
            String projectNumber = "";
            String voucherInfo = "";
            List<String> accuntNumberList =  new ArrayList<>();
            boolean isBankAccount = false;
            /**
             * 先循环凭证，取出现金流量项目编码，因为不知道他在哪一行，所以先循环凭证表头，取现金流量项目编码
             * SAP 现金流量项目编码 在现金科目行上，苍穹的不在现金科目行上
             */
            for (DynamicObject voucherRow : voucherDyns) {
                Map<String, String> auxpropertiesMap = SyncSapFIUtils.getAssGrp(voucherRow);

                if (StringUtils.isNotEmpty(auxpropertiesMap.get("maincfitemNumber"))) {
                    maincfitemNumber = auxpropertiesMap.get("maincfitemNumber");
                }
                if (StringUtils.isNotEmpty(auxpropertiesMap.get("bd_project"))) {
                    projectNumber = auxpropertiesMap.get("bd_project");
                }

                accuntNumberList.add(voucherRow.getString("entries.account.number"));

            }
            /**
             * 当借方和贷方全部都是银行科目，星瀚是不用填写现金流量项目的
             * 此处需要增加现金流量项目编码的默认值 999
             */
            if (StringUtils.isEmpty(maincfitemNumber)) {
                // 检查每个字符串的前四位字符是否都等于指定的前缀
                long count1 = accuntNumberList.stream().filter(s -> s.startsWith("1002")).count();

               if (count1 == accuntNumberList.size()) {
                   maincfitemNumber = "999";
               }
            }

            //voucherDyns 凭证表头与分录平铺
            for (DynamicObject voucherRow : voucherDyns) {
                //String billid = voucherRow.getString("id");
                String companyCode = voucherRow.getString("org.number");

                voucherInfo = companyCode + "|" + voucherRow.getString("vouchertype.name") + "|" + voucherRow.getString("billno");
                Map<String, String> auxpropertiesMap = SyncSapFIUtils.getAssGrp(voucherRow);

                ////处理凭证表头
                HEADERITEMINFO = SyncSapFIUtils.convertCosmicVoucherToSAPForHead(voucherRow);
                JSONObject entry = SyncSapFIUtils.convertCosmicVoucherToSAPForEntry(voucherRow, maincfitemNumber,projectNumber, auxpropertiesMap);
                ENTRY_ITEM.add(entry);

            }

            String jsonData = SyncSapFIUtils.getVoucherData(HEADERITEMINFO, ENTRY_ITEM);
            //System.out.println("凭证 info:" + voucherInfo);
            logger.info("同步SAP凭证 info:" + voucherInfo);
            logger.info("同步SAP凭证 post:" + jsonData);
            String response = SyncSapFIUtils.postDataToSAP("voucher",jsonData);
            logger.info("同步SAP凭证 return:" + response);
            if (StringUtils.isEmpty(response)) {
                err.append("同步失败,SAP凭证:" + voucherInfo);
            }
            JSONObject rsJson = JSONObject.parseObject(response);
            if (rsJson == null) {
                result.put("code", "302");
                result.put("msg", "同步SAP凭证没的返回值，请检查SAP是否正常；");
                return result;
            }
            JSONObject reEt = rsJson.getJSONObject("ET_RETURN");
            JSONArray item = reEt.getJSONArray("item");
            for (int i = 0; i < item.size(); i++) {
                JSONObject itemInfo = item.getJSONObject(i);
                String type = itemInfo.getString("TYPE");
                String msg = itemInfo.getString("MESSAGE");
                String notes = itemInfo.getString("BKTXT");
                if (!"S".equals(type)) {
                    err.append("/n 同步SAP凭证:" + voucherInfo + "，错误信息：" + msg + "|" + notes);
                    logger.info("同步SAP凭证:"  + voucherInfo + "，错误信息：" + msg + "|" + notes);
                    errCount++;
                }else{

                    /**
                     * 需要保存SAP返回的值
                     */
                    // 1. 查询 gl_voucher 对象
                    DynamicObject voucherDyn = BusinessDataServiceHelper.loadSingle(vouchsreId, "gl_voucher");

                    if (voucherDyn != null) {
                        /**
                         * 2. 解析 SAP 返回的 JSON 数据
                         * 同步SAP凭证 retur:{"E_MESSAGE":"创建成功!","E_TYPE":"S","E_XBLNR"."" "ET RETURN":{"item":[{"BKTXT":"BX2010202506-0030","ZZTM""FDZT","TYPE":"S","MESSAGE":"V凭证已成功预制:BKPFF 160000005620102025 S4DCLIT120"}]}}
                         * */
                        String regex = ".*\\s(\\d+)\\s([A-Z0-9]+)";

                        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regex);
                        java.util.regex.Matcher matcher = pattern.matcher(msg);

                        if (matcher.find()) {
                            String eXblnr = matcher.group(1); // 160000005620102025
                           // String bktxt = matcher.group(2); // S4DCLIT120
                            // 3. 设置 gl_voucher 对象的字段
                            voucherDyn.set("nckd_xblnr", eXblnr); // 设置 E_XBLNR 到 nckd_xblnr
                            //voucherDyn.set("nckd_xrlnr_alt", bktxt); // 设置 BKTXT 到 nckd_xrlnr_alt
                        }

                        // 保存更新后的 gl_voucher 对象
                        SaveServiceHelper.save(new DynamicObject[]{voucherDyn});
                    }

                    count++;
                }
            }
        }

        if(StringUtils.isEmpty(err.toString())) {
            result.put("code", "200");
            result.put("msg", "同步SAP凭证，执行成功，本次同步数量"+count);
        }else{
            result.put("code", "300");
            result.put("msg", "但是，同步SAP凭证，本次同步成功数量"+count +",失败数量" + errCount +"，失败信息："+ err);
        }

        return result;
    }

    /**
     * 同步凭证档案号
     *
     * @param companyCode
     * @return
     */

    public Map<String, String> synVoucherArchiveForSap(String companyCode,String year ) {
        Map<String, String> result = new HashMap<>();
        logger.info("同步SAP凭证归档号");
        String data = SyncSapFIUtils.getVoucherArchiveData(companyCode,year);
        logger.info("同步SAP凭证归档号，参数：" + data);
        String response = SyncSapFIUtils.postDataToSAP("voucherArchive", data);
        if (StringUtils.isEmpty(response)) {
            result.put("code", "300");
            result.put("msg", "同步SAP凭证归档号，同步失败");
            return result;
        }
        JSONObject rData = JSONObject.parseObject(response);
//        String etype = rData.getString("E_TYPE");
//
//        if (!"S".equals(etype)) {
//            result.put("code", "301");
//            result.put("msg", "同步SAP凭证归档号，E_TYPE:" + etype + "，错误信息：" + rData.getString("E_MESSGE"));
//            return result;
//        }

        JSONObject rEtItem = rData.getJSONObject("ET_ITEM");
        if (rEtItem == null) {
            result.put("code", "302");
            result.put("msg", "同步SAP凭证归档号，ET_ITEM参数为空");
            return result;
        }

        JSONArray rItemArray = rEtItem.getJSONArray("item");
        if (rItemArray == null) {
            result.put("code", "303");
            result.put("msg", "同步SAP凭证归档号，item参数为空");
            return result;
        }

        Map<String,String> voucherNumberMap = new HashMap<String, String>();
        List<String> voucherNumberList  = new ArrayList<String>();
        for (int i = 0; i < rItemArray.size(); ++i) {
            JSONObject item = rItemArray.getJSONObject(i);
            String number = item.getString("BELNR");
            String SAPvourcherNumber = number + companyCode + year;
            String ArchiveNumber = item.getString("XBLNR_ALT");  //归档号
            if(StringUtils.isNotEmpty(ArchiveNumber)) {
                voucherNumberMap.put(SAPvourcherNumber, ArchiveNumber);
                voucherNumberList.add(SAPvourcherNumber);
            }
        }
        QFilter filter = new QFilter("nckd_xblnr", QCP.in, voucherNumberList);
        DynamicObject[] voucherDyns = BusinessDataServiceHelper.load("gl_voucher",  "id,nckd_xblnr,nckd_xrlnr_alt", new QFilter[]{filter});

        ArrayList<DynamicObject> voucherList = new ArrayList<>();
        for (DynamicObject voucherDyn : voucherDyns) {
            voucherDyn.set("nckd_xrlnr_alt", voucherNumberMap.get(voucherDyn.getString("nckd_xblnr")));
            voucherList.add(voucherDyn);
        }
        if (voucherList.size() > 0) {
            DynamicObject[] saveDynamicObject = voucherList.toArray(new DynamicObject[voucherList.size()]);
            Object[] save = SaveServiceHelper.save(saveDynamicObject);
            int length = save.length;
            logger.info("同步[凭证归档号]完成，本次新增数量：{}" , length);
            result.put("code", "200");
            result.put("msg", "同步SAP凭证归档号，执行成功，本次同步数量" + length);
        }else{
            result.put("code", "200");
            result.put("msg", "同步SAP凭证归档号，执行成功，但本次没有数据！" );
        }

        return result;
    }

}
