package com.malk.chuizi.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.malk.chuizi.config.KDWebApiConf;
import com.malk.chuizi.entity.*;
import com.malk.chuizi.service.ChuiZiService;
import com.malk.chuizi.utils.HttpUtils;
import com.malk.server.aliwork.YDConf;
import com.malk.server.aliwork.YDParam;
import com.malk.server.common.McR;
import com.malk.server.dingtalk.DDR_New;
import com.malk.service.aliwork.YDClient;
import com.malk.service.dingtalk.DDClient;
import com.malk.service.dingtalk.DDClient_Personnel;
import com.malk.service.dingtalk.DDClient_Workflow;
import com.malk.utils.UtilMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;

import static org.junit.Assert.fail;

@Slf4j
@Service
public class ChuiZiServiceImpl implements ChuiZiService {
    @Autowired
    private KDWebApiConf kdWebApiConf;

    @Autowired
    private DDClient ddClient;

    @Autowired
    private DDClient_Personnel ddClientPersonnel;

    @Value("${dingtalk.agentId}")
    private Long agentId;

    @Autowired
    private YDClient ydClient;

    //单据状态
    private static final Map<String,String> FDOCUMENTSTATUS = new HashMap<>();
    static{
        FDOCUMENTSTATUS.put("Z","暂存");
        FDOCUMENTSTATUS.put("A","创建");
        FDOCUMENTSTATUS.put("B","审核中");
        FDOCUMENTSTATUS.put("C","已审核");
        FDOCUMENTSTATUS.put("D","重新审核");
    }

    //整单状态
    private static final Map<String,String> AUDITSTATUS = new HashMap<>();
    static{
        AUDITSTATUS.put("U","未审核");
        AUDITSTATUS.put("A","已审核");
        AUDITSTATUS.put("I","审核中");
        AUDITSTATUS.put("P","部分审核");
        AUDITSTATUS.put("R","重新审核");
    }

    //禁用状态
    private static final Map<String,String> FFORBIDSTATUS = new HashMap<>();
    static{
        FFORBIDSTATUS.put("A","否");
        FFORBIDSTATUS.put("B","是");
    }

    private static final Map<String,String> FFORBIDDENSTATUS = new HashMap<>();
    static{
        FFORBIDDENSTATUS.put("0","否");
        FFORBIDDENSTATUS.put("1","是");
    }

    private static final Map<String,String> FERPCLSID = new HashMap<>();
    static {
        FERPCLSID.put("10","资产");
        FERPCLSID.put("9","配置");
        FERPCLSID.put("2","自制");
        FERPCLSID.put("11","费用");
        FERPCLSID.put("12","模型");
        FERPCLSID.put("5","虚拟");
        FERPCLSID.put("7","一次性");
        FERPCLSID.put("13","产品系列");
        FERPCLSID.put("3","委外");
        FERPCLSID.put("4","特征");
        FERPCLSID.put("6","服务");
        FERPCLSID.put("1","外购");
    }

    private static final Map<String,String> BUSINESS_TYPE = new HashMap<>();
    static {
        BUSINESS_TYPE.put("8","发货检验");
        BUSINESS_TYPE.put("25","生产退料检验");
        BUSINESS_TYPE.put("26","委外退料检验");
        BUSINESS_TYPE.put("3","产品检验");
        BUSINESS_TYPE.put("20","其他检验");
        BUSINESS_TYPE.put("6","委外工序");
        BUSINESS_TYPE.put("10","受托材料检验");
        BUSINESS_TYPE.put("2","委外检验");
        BUSINESS_TYPE.put("21","工序巡检");
        BUSINESS_TYPE.put("7","退货检验");
        BUSINESS_TYPE.put("9","生产线检验");
        BUSINESS_TYPE.put("1","采购检验");
        BUSINESS_TYPE.put("4","库存检验");
        BUSINESS_TYPE.put("5","工序自制");
    }

    private static final Map<String,String> INSPECT_RESULT = new HashMap<>();
    static {
        INSPECT_RESULT.put("1","合格");
        INSPECT_RESULT.put("2","不合格");
        INSPECT_RESULT.put("3","保留");
    }
    private static final Map<String,String> DEPARTMENT = new HashMap<>();
    static {
        DEPARTMENT.put("经营管理部","CZ00104");
        DEPARTMENT.put("人事行政部","CZ00105");
        DEPARTMENT.put("销售部","CZ00106");
        DEPARTMENT.put("技术部","CZ00107");
        DEPARTMENT.put("IT部门","CZ00107");
        DEPARTMENT.put("后勤部","CZ00108");
        DEPARTMENT.put("资材部","CZ00109");
        DEPARTMENT.put("原料仓库组","CZ0010902");
        DEPARTMENT.put("成品仓库组","CZ0010903");
        DEPARTMENT.put("生产计划组","CZ0010904");
        DEPARTMENT.put("客户服务组","CZ0010905");
        DEPARTMENT.put("品质部","CZ00110");
        DEPARTMENT.put("一车间检验组","CZ0011001");
        DEPARTMENT.put("二车间检验组","CZ0011002");
        DEPARTMENT.put("三车间检验组","CZ0011003");
        DEPARTMENT.put("生产部","CZ00111");
        DEPARTMENT.put("一车间生产组","CZ0011101");
        DEPARTMENT.put("二车间生产组","CZ0011103");
        DEPARTMENT.put("三车间生产组","CZ0011105");
        DEPARTMENT.put("总经办","CZ00101");
        DEPARTMENT.put("审计部","CZ00102");
        DEPARTMENT.put("财务部","CZ00103");
    }
    private static final Map<String,String> PAYMENT_METHOD = new HashMap<>();
    static {
        PAYMENT_METHOD.put("现金","JSFS01_SYS");
        PAYMENT_METHOD.put("现金支票","JSFS02_SYS");
        PAYMENT_METHOD.put("转账支票","JSFS03_SYS");
        PAYMENT_METHOD.put("电汇","JSFS04_SYS");
        PAYMENT_METHOD.put("信汇","JSFS05_SYS");
        PAYMENT_METHOD.put("商业承兑汇票","JSFS06_SYS");
        PAYMENT_METHOD.put("银行承兑汇票","JSFS07_SYS");
        PAYMENT_METHOD.put("信用证","JSFS08_SYS");
        PAYMENT_METHOD.put("应收票据背书","JSFS09_SYS");
        PAYMENT_METHOD.put("票据退票","JSFS12_SYS");
        PAYMENT_METHOD.put("保证金转货款","JSFS22_SYS");
        PAYMENT_METHOD.put("微信","JSFS31_SYS");
        PAYMENT_METHOD.put("支付宝","JSFS32_SYS");
        PAYMENT_METHOD.put("供应链票据","JSFS36_SYS");
        PAYMENT_METHOD.put("内部转销","JSFS41_SYS");
        PAYMENT_METHOD.put("认领结算","JSFS81_SYS");

    }
    private IdentifyInfo initIden(){
        //注意 1：此处不再使用参数形式传入用户名及密码等敏感信息，改为在登录配置文件中设置。
        //注意 2：必须先配置第三方系统登录授权信息后，再进行业务操作，详情参考各语言版本SDK介绍中的登录配置文件说明。
        //读取配置，初始化SDK
        IdentifyInfo iden = new IdentifyInfo();
        iden.setUserName(kdWebApiConf.getXKDApiUserName());
        iden.setAppId(kdWebApiConf.getXKDApiAppID());
        iden.setdCID(kdWebApiConf.getXKDApiAcctID());
        iden.setAppSecret(kdWebApiConf.getXKDApiAppSec());
        iden.setServerUrl(kdWebApiConf.getXKDApiServerUrl());

        return iden;
    }

    private String getString(Object object){
        return object == null ? "" : object.toString();
    }


    /// dingtalk
    final String APP_EKY = "ding9seotugcsfjlgy8h";
    final String APP_SECRET = "4k6hoCDUwwpUG5WXijfWcnzIm97j_zGquJqXJgrkBcyp2vo7ceV6dO-nSDUUDMhE";
    @Override
    public McR saveOtherMeet(Map processData) {
        String userId = String.valueOf(processData.get("originatorUserId"));
        String workId = getNumberByUserId(userId);
        Save save = new Save();

        Model otherMeet = new Model();
        otherMeet.setFCONTACTUNITTYPE("BD_Empinfo");
        otherMeet.setFBillTypeID(new BillTypeID("QTYFD02_SYS"));
        otherMeet.setFCONTACTUNIT(new FNumber(workId));//员工号
        otherMeet.setFDATE(LocalDateTimeUtil.format(LocalDate.now(),"yyyy-MM-dd"));
        otherMeet.setFENDDATE_H(LocalDateTimeUtil.format(LocalDate.now(),"yyyy-MM-dd"));
        otherMeet.setFCURRENCYID(new FNumber("PRE001"));//币别
        final double[] sum = {0.0,0.0};
        List<Map> formComponentValues = (List<Map>) processData.get("formComponentValues");
        Map<String, Object> mainData = new HashMap<>();
        List<Map<String,Object>> sonData = new ArrayList<>();
        formComponentValues.forEach(e->{
            String name = e.get("name").toString();
            if ("金蝶科目".equals(name) || "报销科目".equals(name) || "归属部门".equals(name) || "发票类型".equals(name) || "申请人".equals(name) || "报销类型".equals(name) || "金额".equals(name)) {
                mainData.put(name, e.get("value"));
            } else if ("TableField".equals(e.get("componentType"))) {
                Object parse = JSON.parse(e.get("value").toString());
                JSONArray jsonArray = JSON.parseArray(parse.toString());
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = (JSONObject) jsonArray.get(i);
                    Object rowValue = jsonObject.get("rowValue");
                    JSONArray array = JSON.parseArray(rowValue.toString());
                    for (int i1 = 0; i1 < array.size(); i1++) {
                        jsonObject = (JSONObject) array.get(i1);
                        if (jsonObject.containsKey("extendValue")){
                            rowValue = jsonObject.get("extendValue");
                            jsonObject = JSONObject.parseObject(rowValue.toString());
                            rowValue = jsonObject.get("list");
                            JSONArray array1 =  JSON.parseArray(rowValue.toString());
                            for (int i2 = 0; i2 < array1.size(); i2++) {
                                jsonObject = (JSONObject) array1.get(i2);
                                if (jsonObject.containsKey("rowValue")){
                                    rowValue = jsonObject.get("rowValue");
                                    JSONArray array2 = JSON.parseArray(rowValue.toString());
                                    for (int l = 0; l < array2.size(); l++) {
                                        Map<String, Object> map = new HashMap<>();
                                        jsonObject = (JSONObject) array2.get(l);
                                        //需要改成金额
                                        if ("金额".equals(jsonObject.get("label"))){
                                            double amount = Double.parseDouble(jsonObject.get("value") == null ? "0.0" : jsonObject.get("value").toString());
                                            sum[0] = sum[0] + amount;
                                            sum[1] = sum[1] + amount;
                                            map.put("amount",amount);

                                            sonData.add(map);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
        List<Object> objects  = new ArrayList<>();
        if ("管理费用报销".equals(mainData.get("报销类型"))){
            OtherMeetEntity otherMeetEntity = new OtherMeetEntity();
            otherMeetEntity.setFCOSTID(new FNumber(mainData.get("金蝶科目").toString()));
            otherMeetEntity.setFINVOICETYPE(mainData.get("发票类型").toString());
            otherMeetEntity.setFCOSTDEPARTMENTID(new FNumber(DEPARTMENT.get(mainData.get("归属部门").toString())));
            otherMeetEntity.setFEntryTaxRate(0.0);
            otherMeetEntity.setFNOTAXAMOUNTFOR(Double.parseDouble(mainData.get("金额").toString()));
            otherMeetEntity.setFTAXAMOUNTFOR(0.0);
            otherMeetEntity.setFTOTALAMOUNTFOR(Double.parseDouble(mainData.get("金额").toString()));
            otherMeetEntity.setFPaySubEntity(null);

            objects.add(otherMeetEntity);

        }else if(ObjectUtil.isNotNull(sonData) && sonData.size()>0){
            sonData.forEach(e->{
                OtherMeetEntity otherMeetEntity = new OtherMeetEntity();
                otherMeetEntity.setFCOSTID(new FNumber(mainData.get("金蝶科目").toString()));
                otherMeetEntity.setFINVOICETYPE(mainData.get("发票类型").toString());
                otherMeetEntity.setFCOSTDEPARTMENTID(new FNumber(DEPARTMENT.get(mainData.get("归属部门").toString())));
                otherMeetEntity.setFEntryTaxRate(0.0);
                otherMeetEntity.setFNOTAXAMOUNTFOR(Double.parseDouble(e.get("amount").toString()));
                otherMeetEntity.setFTAXAMOUNTFOR(0.0);
                otherMeetEntity.setFTOTALAMOUNTFOR(Double.parseDouble(e.get("amount").toString()));
                otherMeetEntity.setFPaySubEntity(null);

                objects.add(otherMeetEntity);
            });
        }
        otherMeet.setFEntity(objects);

        save.setModel(otherMeet);
//        System.out.println(save);

        try{
            K3CloudApi client = new K3CloudApi(initIden());
            //业务对象标识
            String formId = "AP_OtherPayable";
            //调用接口
            String resultJson = client.save(formId,JSONObject.toJSONString(save));
            //用于记录结果
            Gson gson = new Gson();
            //对返回结果进行解析和校验
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);

            if (isTrue(repoRet)){
                String id = repoRet.getResult().getId();

                Submit submit = new Submit();
                submit.setIds(id);
                //提交
                String resultJson2 = client.submit(formId, JSONObject.toJSONString(submit));
                RepoRet repoRet2 = gson.fromJson(resultJson2, RepoRet.class);
                isTrue(repoRet2);

//                String orderCode = repoRet2.getResult().getResponseStatus().getSuccessEntitys().get(0).getNumber();

//                ydClient.operateData(YDParam.builder()
////                        .formInstId(formInstId)
//                        .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_m6yntxmz",orderCode)))
//                        .build(), YDConf.FORM_OPERATION.update);

                if (isTrue(repoRet2)){
                    Audit audit = new Audit();
                    audit.setIds(id);
                    //审核
                    String resultJson3 = client.audit(formId,JSONObject.toJSONString(audit));
                    RepoRet repoRet3 = gson.fromJson(resultJson3, RepoRet.class);
                    isTrue(repoRet3);
                }
            }
        } catch (Exception e) {
            McR.errorUnknown(e.getMessage());
        }

        return McR.success();
    }

    @Override
    public McR saveAccountsPayable(Map processData) {
//        String userId = String.valueOf(processData.get("originatorUserId"));
        Save save = new Save();

        Model model = new Model();

        model.setFDATE(LocalDateTimeUtil.format(LocalDate.now(),"yyyy-MM-dd"));
        model.setFCURRENCYID(new FNumber("PRE001"));//币别
        List<Map> formComponentValues = (List<Map>) processData.get("formComponentValues");

        Map<String, Object> mainData = new HashMap<>();

        formComponentValues.forEach(e->{
            String name = e.get("name").toString();
            mainData.put(name, e.get("value"));
        });
        List<AccountsPayableEntity> objects  = new ArrayList<>();
        if (ObjectUtil.isNotNull(mainData)){
            if ("采购业务付款单".equals(mainData.get("单据类型"))){
                //主表
                model.setFREMARK(mainData.get("付款事由").toString());
                model.setFRECTUNIT(new FNumber(mainData.get("供应商编码").toString()));
                model.setFCONTACTUNIT(new FNumber(mainData.get("供应商编码").toString()));
                model.setFCONTACTUNITTYPE("BD_Supplier");
                model.setFBillTypeID(new BillTypeID("FKDLX01_SYS"));
            }else {
                //主表
                model.setFREMARK(mainData.get("付款事由").toString());
                model.setFRECTUNITTYPE("BD_Empinfo");
                model.setFRECTUNIT(new FNumber("003"));
                model.setFCONTACTUNITTYPE("BD_Empinfo");
                model.setFCONTACTUNIT(new FNumber("003"));
                model.setFBillTypeID(new BillTypeID("FKDLX03_SYS"));
            }
            //明细
            AccountsPayableEntity accountsPayableEntity = new AccountsPayableEntity();
            accountsPayableEntity.setFSETTLETYPEID(new FNumber(PAYMENT_METHOD.get(mainData.get("付款方式"))));//结算方式
            accountsPayableEntity.setFPURPOSEID(new FNumber(mainData.get("付款用途编码").toString()));//付款用途
            accountsPayableEntity.setFPAYTOTALAMOUNTFOR(Double.parseDouble(mainData.get("付款总额").toString()));
            accountsPayableEntity.setFPAYAMOUNTFOR_E(Double.parseDouble(mainData.get("付款总额").toString()));

            objects.add(accountsPayableEntity);
        }
        model.setFPAYBILLENTRY(objects);

        save.setModel(model);
        System.out.println(save);

        try{
            K3CloudApi client = new K3CloudApi(initIden());
            //业务对象标识
            String formId = "AP_PAYBILL";
            //调用接口
            String resultJson = client.save(formId,JSONObject.toJSONString(save));
            //用于记录结果
            Gson gson = new Gson();
            //对返回结果进行解析和校验
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);

            if (isTrue(repoRet)){
                String id = repoRet.getResult().getId();

                Submit submit = new Submit();
                submit.setIds(id);
                //提交
                String resultJson2 = client.submit(formId, JSONObject.toJSONString(submit));
                RepoRet repoRet2 = gson.fromJson(resultJson2, RepoRet.class);
                isTrue(repoRet2);

                if (isTrue(repoRet2)){
                    Audit audit = new Audit();
                    audit.setIds(id);
                    //审核
                    String resultJson3 = client.audit(formId,JSONObject.toJSONString(audit));
                    RepoRet repoRet3 = gson.fromJson(resultJson3, RepoRet.class);
                    isTrue(repoRet3);
                }
            }
        } catch (Exception e) {
            McR.errorUnknown(e.getMessage());
        }

        return McR.success();
    }

    @Override
    public McR rechargeFuelCard(Map processData) {
        //身份认证参数
        Map headers = new HashMap();
        headers.put("EngineCode","o3mum9h68yl3v8g1o3ft2aek7");
        headers.put("EngineSecret","yeFjbv44SHwG9GThAfNCmJYqM+FfKYNTHp6Lw31T7KwhB3qKu5dv2w==");
        headers.put("Content-Type","application/json");

        List<Map> formComponentValues = (List<Map>) processData.get("formComponentValues");

        Map<String, Object> mainData = new HashMap<>();
        formComponentValues.forEach(e->{
            String name = e.get("name").toString();
            mainData.put(name, e.get("value"));
        });


        Map<String, String> paramMap = new HashMap();
        paramMap.put("ActionName",   "LoadBizObjects");
        paramMap.put("SchemaCode", "D285303f3713e1dfc2d4bb5be5c41ce4b1d545b");
        paramMap.put("Filter","{\"FromRowNum\":0,\"RequireCount\": false,\"ReturnItems\":[],\"SortByCollection\":[],\"ToRowNum\":500,\"Matcher\":{\"Type\":\"And\",\"Matchers\":[{\"Type\":\"And\",\"Matchers\":[{\"Type\":\"Item\",\"Name\":\"F0000002\",\"Operator\":2,\"Value\":\""+mainData.get("车牌").toString()+"\"}]}]}}");

        final String[] BizObject = {"",""};
        String result = HttpUtils.httpPost("https://www.h3yun.com/OpenApi/Invoke",   paramMap, headers);
        log.info(result);
        JSONObject jsonObject = (JSONObject) JSONObject.parse(result);
        jsonObject = (JSONObject) jsonObject.get("ReturnData");
        JSONArray jsonArray = JSONArray.parseArray(jsonObject.get("BizObjectArray").toString());
        jsonArray.forEach(e->{
            JSONObject value = (JSONObject) JSONObject.parse(e.toString());
            BizObject[0] = value.getString("ObjectId");
            BizObject[1] = value.get("F0000006").toString();
        });
        System.out.println(BizObject[0]+" "+BizObject[1]);
        System.out.println(jsonArray);
        double amount = BizObject[1] == null || BizObject[1].isEmpty() ? 0.0 : Double.parseDouble(BizObject[1]);
        paramMap.put("ActionName","UpdateBizObject");
        paramMap.put("SchemaCode","D285303f3713e1dfc2d4bb5be5c41ce4b1d545b");
        paramMap.put("BizObjectId",BizObject[0]);
        paramMap.remove("Filter");
        paramMap.put("BizObject",JSON.toJSONString(UtilMap.map("F0000006",BigDecimal.valueOf(amount).add(BigDecimal.valueOf(100)))));

        result = HttpUtils.httpPost("https://www.h3yun.com/OpenApi/Invoke",   paramMap, headers);
        log.info(result);
        return McR.success();
    }

    public String getNumberByUserId(String workingEmployeeIds) {
//        log.info("根据钉钉人员id获取员工工号:{}",workingEmployeeIds);
        List<String> filterList = new ArrayList<>();
        filterList.add("sys00-jobNumber");
        List<Map> employeeInfos = ddClientPersonnel.getEmployeeInfos(ddClient.getAccessToken(), Arrays.asList(workingEmployeeIds), agentId, filterList);
        final String[] value = {""};
        employeeInfos.forEach(e -> {
            List<Map> mapList = (List<Map>) e.get("field_data_list");
            mapList.forEach(m -> {
                List<Map> valueList = (List<Map>) m.get("field_value_list");
                value[0] = ObjectUtil.isNotNull(valueList.get(0).get("value")) ? valueList.get(0).get("value").toString() : null;
            });
        });
        return value[0];
    }

    private String getMultiLanguageTextName(Object object){
        if (Objects.nonNull(object)){
            Map map = (Map) object;
            List<Map> multiLanguageText = (List<Map>) map.get("MultiLanguageText");
            String value = getString(multiLanguageText.get(0).get("Name"));

            return value;
        }
        return null;
    }

    private String getMultiLanguageTextSpecification(Object object){
        if (Objects.nonNull(object)){
            Map map = (Map) object;
            List<Map> multiLanguageText = (List<Map>) map.get("MultiLanguageText");
            String value = getString(multiLanguageText.get(0).get("Specification"));

            return value;
        }
        return null;
    }

    private String getEntryNumber(Object object){
        if (Objects.nonNull(object)){
            Map map = (Map) object;
            String value =  getString(map.get("Number"));

            return value;
        }
        return null;
    }


    private boolean isTrue(RepoRet repoRet){
        Gson gson = new Gson();

        if (repoRet.getResult().getResponseStatus().isIsSuccess()) {
            System.out.printf("接口返回结果: %s%n", gson.toJson(repoRet.getResult()));
            return true;
        } else {
            fail("接口返回结果: " + gson.toJson(repoRet.getResult().getResponseStatus()));
            return false;
        }
    }

    private List<Map> getYdFormDataList(String formUuid, String searchCondition, YDConf.FORM_QUERY formQuery) {
        List<Map> list = new ArrayList<>();
        DDR_New ddrNew = new DDR_New();
        int pageNumber = 1;
        int pageSize = 100;
        do {
            ddrNew = ydClient.queryData(YDParam.builder().formUuid(formUuid)
                    .searchCondition(searchCondition)
                    .pageNumber(pageNumber)
                    .pageSize(pageSize).build(), formQuery);

            list.addAll((List<Map>) ddrNew.getData());
            pageNumber++;
        }while (ddrNew.getTotalCount() > ddrNew.getPageNumber() * pageSize);
        return list;
    }


}
