package nckd.jimin.jyyy.bd.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.dynamicobject.DynamicObjectType;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.exception.KDException;
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.schedule.api.StopTask;
import kd.bos.schedule.executor.AbstractTask;
import kd.bos.sdk.util.KHttpClientUtils;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.basedata.BaseDataServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.util.StringUtils;
import nckd.base.helper.CommonHelperUtils;

import javax.management.Query;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 调度任务类
 * 插件说明：查询SAP接口获取在SAP系统中手工新增的财务类供应商，同步至星瀚的指定分类下
 * @author wanghaiwu
 * @date 2025/04/23
 */
public class SynSupplierFromSAPTask extends AbstractTask implements StopTask {
    private static final Log logger = LogFactory.getLog(SynSupplierFromSAPTask.class);
    protected static final Long DEFAULT_ORG_ID = 100000L;
    private static final String ENTITY_SUPPLIER = "bd_supplier";
    private static String param_suppliertype_5 = "";
    private static String param_suppliertype_ee = "";
    private static String param_supplierurl = "";
    private static String param_username = "";
    private static String param_password = "";

    @Override
    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
        Map<String, String> mapentity = CommonHelperUtils.getCommonParams("SAP");
        if(mapentity == null){
            return;
        }

        param_suppliertype_5 = mapentity.get("suppliertype_5");
        param_suppliertype_ee = mapentity.get("suppliertype_EE");
        param_supplierurl = mapentity.get("supplier_url");
        param_username = mapentity.get("username");
        param_password = mapentity.get("password");

        if(StringUtils.isEmpty(param_suppliertype_5) || StringUtils.isEmpty(param_suppliertype_ee) || StringUtils.isEmpty(param_supplierurl)
                || StringUtils.isEmpty(param_username) || StringUtils.isEmpty(param_password)){
            return;
        }

        Map<String, SupplierModel> supplierNameMap = new HashMap<String, SupplierModel>();
        Map<String, List<String>> supplierOrgMap = new HashMap<String, List<String>>();


        String encoded = Base64.getEncoder().encodeToString((param_username + ":" + param_password).getBytes());
        Map<String, String> header = new HashMap<>();
        header.put("Content-Type", "application/json; charset=UTF-8");
        header.put("Authorization", "Basic " + encoded);

        //属性核算组织=是
        QFilter qFilter = new QFilter("fisaccounting", QCP.equals, "1");
        //使用状态=启用
        qFilter.and(new QFilter("enable", QCP.equals, "1"));
        //数据状态=已审核
        qFilter.and(new QFilter("status", QCP.equals, "C"));

        DynamicObject[] orgLst = BusinessDataServiceHelper.load("bos_org", "id, number", qFilter.toArray());

        //轮询组织，将供应商信息缓存到Map中
        for(DynamicObject org : orgLst) {
            logger.info("------同步组织 " + org.getString("number") + "(" + org.getString("number") + ")下的供应商----------");
            String orgNumber = org.getString("number");

            buildSupplier(supplierNameMap, supplierOrgMap, param_supplierurl, header, orgNumber, map);
        }

        if(supplierNameMap.size() > 0){
            for (Map.Entry<String, SupplierModel> frameOrgMap : supplierNameMap.entrySet()) {
                String number = frameOrgMap.getKey();
                SupplierModel sModel = frameOrgMap.getValue();

                JSONObject jsonData = new JSONObject();
                jsonData.put("number", number);
                jsonData.put("name", sModel.getName());
                jsonData.put("group", sModel.getGroup());

                List<String> orgList = supplierOrgMap.get(number);
                jsonData.put("orgList", orgList);

                synSupplier(jsonData);
            }
        }
    }

    /**
     *
     * @param supplierNameMap
     * @param supplierOrgMap
     * @param url
     * @param header
     * @param orgNumber
     */
    private void buildSupplier(Map<String, SupplierModel> supplierNameMap, Map<String, List<String>> supplierOrgMap
                                , String url, Map<String, String> header, String orgNumber, Map<String, Object> map){
        try {


            JSONObject jsonData = new JSONObject();

            jsonData.put("BUKRS", orgNumber);
            jsonData.put("LIFNR", "");
            jsonData.put("NAME1", "");

            JSONObject etItemData = new JSONObject();
            JSONObject itemData = new JSONObject();
            itemData.put("BUKRS", "");
            itemData.put("LIFNR", "");
            itemData.put("NAME1", "");

            etItemData.put("item", itemData);

            jsonData.put("ET_ITEM", etItemData);

            String result = KHttpClientUtils.postjson(url, header, JSON.toJSONString(jsonData));

            if(result == null){
                logger.info("调用接口失败:" + url);
                return;
            }

            JSONObject rData = JSONObject.parseObject(result);

            String etype = rData.getString("E_TYPE");

            if(!"S".equals(etype)){
                return;
            }

            JSONObject rEtItem = rData.getJSONObject("ET_ITEM");
            if(rEtItem == null){
                return;
            }

            JSONArray rItemArray = rEtItem.getJSONArray("item");
            if(rItemArray == null){
                return;
            }

            int size = 0;
            int maxSize = 0;
            if(map.get("maxCount") != null){
                maxSize = Integer.parseInt(map.get("maxCount").toString());
            }

            for(int i = 0; i < rItemArray.size(); ++i) {
                JSONObject item = rItemArray.getJSONObject(i);
                String number = item.getString("LIFNR");

                if(StringUtils.isNotEmpty(number)
                        && ("5".equals(number.substring(0, 1)) || "EE".equals(number.substring(0, 2))) ){
                    size++;

                    if(maxSize > 0 && size > maxSize){
                        break;
                    }

                    String name = item.getString("NAME1");

                    if(!supplierNameMap.containsKey(number)){
                        SupplierModel smodel = new SupplierModel();

                        smodel.setNumber(number);
                        smodel.setName(name);
                        if("5".equals(number.substring(0, 1))){
                            smodel.setGroup(param_suppliertype_5);
                        } else if("EE".equals(number.substring(0, 2))){
                            //EE开头，如果未匹配到员工编号，则不同步
                            if(!isEmployee(number)){
                                continue;
                            }
                            smodel.setGroup(param_suppliertype_ee);
                        }

                        supplierNameMap.put(number, smodel);
                    }

                    List<String> orgList = null;
                    if(supplierOrgMap.containsKey(number)){
                        orgList = supplierOrgMap.get(number);
                        orgList.add(orgNumber);
                    } else {
                        orgList = new ArrayList<String>();
                        orgList.add(orgNumber);
                    }
                    supplierOrgMap.put(number, orgList);
                }
            }
        } catch (IOException e) {
            logger.info(e.getMessage());
        }
    }

    /**
     * 校验员工供应商是否是本公司的人员
     * @param supplierNumber
     * @return
     */
    private boolean isEmployee(String supplierNumber){
        supplierNumber = supplierNumber.replace("EE", "");
        QFilter qFilter = new QFilter("number", QCP.equals, supplierNumber);

        return QueryServiceHelper.exists("bos_user", qFilter.toArray());
    }

    /**
     * 同步供应商
     * @param jsonData
     * @return
     */
    private Map<String, String> synSupplier(JSONObject jsonData){
        Map<String, String> returnMap = new HashMap<>();

        //供应商编码
        String supplierNumber = jsonData.getString("number");
        //供应商名称
        String supplierName = jsonData.getString("name");
        //供应商分组
        String supplierGroup = jsonData.getString("group");

        //供应商类型：法人企业1，非法人企业2，非企业单位3，个人4，个体户5
        if(StringUtils.isEmpty(supplierNumber)){
            returnMap.put("code", "500");
            returnMap.put("msg", "供应商编码为空！");

            return returnMap;
        }

        if(StringUtils.isEmpty(supplierName)){
//            supplierName = supplierNumber;

            returnMap.put("code", "500");
            returnMap.put("msg", "供应商名称为空！");

            return returnMap;
        }

        String type = "1";
        if(supplierName.length() < 4){
            type = "4";
        }

        boolean isUpdate = false;
        Long supplierId = 0L;
        Date curDate = new Date();

        //默认创建组织
        DynamicObject defaultOrg = BusinessDataServiceHelper.loadSingle(DEFAULT_ORG_ID, "bos_org");

        QFilter qFilter = new QFilter("createorg", QCP.equals, DEFAULT_ORG_ID);
        qFilter.and(new QFilter("number", QCP.equals, supplierNumber));

        DynamicObject supplier = BusinessDataServiceHelper.loadSingleFromCache(ENTITY_SUPPLIER, qFilter.toArray());
        if (supplier == null) {
            supplier = BusinessDataServiceHelper.newDynamicObject(ENTITY_SUPPLIER);
            supplier.set("status", "A");
            supplier.set("createtime", curDate);
        } else {
            supplierId = supplier.getLong("id");
            isUpdate = true;
        }

        supplier.set("nckd_datasource", "sap");
//        supplier.set("societycreditcode", "test");

        supplier.set("type", type);
        supplier.set("number", supplierNumber);
        supplier.set("name", supplierName);
        if ("4".equals(type)) {
            supplier.set("idno", supplierNumber);
        }

        //管控策略：1、逐级分配；2、自由分配；5、全局共享；6、管控范围内共享；7、私有
        supplier.set("ctrlstrategy", 2);

        //使用状态：0、禁用；1、可用
        supplier.set("enable", "1");

        //业务职能：1、采购；2、结算；3、付款；4、收货
        supplier.set("bizfunction", ",1,2,3,4,");

        //供应商状态：
        qFilter  = new QFilter("number", QCP.equals, "ZCGYS");
        DynamicObject supplierStatus = BusinessDataServiceHelper.loadSingleFromCache("bd_supplierstatus", "id, number, name", qFilter.toArray());
        if(supplierStatus != null) {
            supplier.set("supplier_status", supplierStatus);
        }

        RequestContext rc = RequestContext.get();
        DynamicObject user = BusinessDataServiceHelper.loadSingle(rc.getCurrUserId(), "bos_user");
        supplier.set("creator", user);
        supplier.set("createorg", defaultOrg);
        supplier.set("org", defaultOrg);

        qFilter = new QFilter("number", QCP.equals, supplierGroup);
        qFilter.and(new QFilter("enable", QCP.equals, "1"));
        qFilter.and(new QFilter("status", QCP.equals, "C"));
        DynamicObject suppliergroup = BusinessDataServiceHelper.loadSingleFromCache("bd_suppliergroup", "id, number, name, standard", qFilter.toArray());
        supplier.set("group", suppliergroup);

//        DynamicObject groupstandard = BusinessDataServiceHelper.loadSingleFromCache("bd_suppliergroupstandard", "id, number, name", qFilter.toArray());
        //子分录--默认分类（支持多分类）
        DynamicObjectCollection groupstandardCol = supplier.getDynamicObjectCollection("entry_groupstandard");
        //先清除分类
        groupstandardCol.clear();

        DynamicObjectType billtype = groupstandardCol.getDynamicObjectType();
        DynamicObject groupdetail = new DynamicObject(billtype);
        groupdetail.set("standardid", suppliergroup.getDynamicObject("standard"));
        groupdetail.set("groupid", suppliergroup);
        groupstandardCol.add(groupdetail);
        supplier.set("entry_groupstandard", groupstandardCol);

        //判断是否更新与新增，通过不同方法处理，保存操作会变更状态为保存
        if(isUpdate) {
//            SaveServiceHelper.update(new DynamicObject[]{customer});
            OperationResult resultSave = SaveServiceHelper.saveOperate(ENTITY_SUPPLIER, new DynamicObject[]{supplier}, OperateOption.create());

            StringBuilder err = new StringBuilder();
            if (resultSave.getSuccessPkIds().size() <= 0) {
                for (int i = 0; i < resultSave.getAllErrorOrValidateInfo().size(); i++) {
                    String message = resultSave.getAllErrorOrValidateInfo().get(i).getMessage();
                    err.append("/").append(message);
                }
                logger.info(err.toString());
                return returnMap;
            }
            supplierId = supplier.getLong("id");
        }else {
            //新增保存供应商对象
            OperationResult resultSave = SaveServiceHelper.saveOperate(ENTITY_SUPPLIER, new DynamicObject[]{supplier}, OperateOption.create());

            StringBuilder err = new StringBuilder();
            if (resultSave.getSuccessPkIds().size() <= 0) {
                for (int i = 0; i < resultSave.getAllErrorOrValidateInfo().size(); i++) {
                    String message = resultSave.getAllErrorOrValidateInfo().get(i).getMessage();
                    err.append("/").append(message);
                }

                logger.info(err.toString());
                return returnMap;
            } else {
                supplierId = (Long) resultSave.getSuccessPkIds().get(0);
            }
            DynamicObject customerObj = BusinessDataServiceHelper.loadSingle(supplierId, "bd_supplier");

            OperationResult resultSubmit = OperationServiceHelper.executeOperate("submit", ENTITY_SUPPLIER, new DynamicObject[]{customerObj}, OperateOption.create());
            err.setLength(0);

            if (resultSubmit.getSuccessPkIds().size() <= 0) {
                for (int i = 0; i < resultSubmit.getAllErrorOrValidateInfo().size(); i++) {
                    String message = resultSubmit.getAllErrorOrValidateInfo().get(i).getMessage();
                    err.append("/").append(message);
                }

                returnMap.put("code", "500");
                returnMap.put("msg", err.toString());

                return returnMap;
            }

            OperationResult resultAudit = OperationServiceHelper.executeOperate("audit", ENTITY_SUPPLIER, new DynamicObject[]{customerObj}, OperateOption.create());
            err.setLength(0);

            if (resultAudit.getSuccessPkIds().size() <= 0) {
                for (int i = 0; i < resultAudit.getAllErrorOrValidateInfo().size(); i++) {
                    String message = resultAudit.getAllErrorOrValidateInfo().get(i).getMessage();
                    err.append("/").append(message);
                }

                returnMap.put("code", "500");
                returnMap.put("msg", err.toString());

                return returnMap;
            }
        }

        //组织分配
        if(jsonData.get("orgList") != null){
            List<Long> assignOrgIds = new ArrayList<>();
            List<String> orgCodeList = (List<String>)jsonData.get("orgList");
            List<String> orgCodeKdList = new ArrayList<>();

            QFilter orgFilter = new QFilter("number", QCP.in, orgCodeList);
            orgFilter.and(new QFilter("enable", QCP.equals, "1"));
            orgFilter.and(new QFilter("status", QCP.equals, "C"));

            DynamicObject[] orgList = BusinessDataServiceHelper.load("bos_org", "id, number", orgFilter.toArray());

            for(DynamicObject org : orgList){
                assignOrgIds.add(org.getLong("id"));
                orgCodeKdList.add(org.getString("number"));
            }

            if(assignOrgIds.size() > 0) {
                String assignResult = assignOrg2Supplier(supplierId, assignOrgIds);

                if (assignResult.isEmpty()) {
                    logger.info("同步成功、分配成功");
                } else {
                    logger.info("同步成功、分配失败");
                }

                if(orgCodeKdList.size() != orgCodeList.size()){
                    List<String> differenceList = orgCodeKdList.stream().filter(item -> !orgCodeKdList.contains(item)).collect(Collectors.toList());
                    if(differenceList.size() > 0){
                        String unAssignOrgString = String.join(",", differenceList);

                        logger.info("同步成功、部分组织分配失败：" + unAssignOrgString + ", 这些组织在星瀚中未匹配到！");
                    }
                }
            }
        }

        return returnMap;
    }

    /**
     * 客户分配组织
     * @param supplierId
     * @param assignOrgIds
     * @return
     */
    public String assignOrg2Supplier(Long supplierId, List<Long> assignOrgIds) {
        String result = "";

        ArrayList<Long> dataIds = new ArrayList();
        dataIds.add(supplierId);

        List<Long> assignOrgList = BaseDataServiceHelper.getAssignDesOrgs(DEFAULT_ORG_ID,"2",16L);
        //取交集
        Set<Long> intersectOrgs = intersectionLong(assignOrgList, assignOrgIds);
        Map<Long, Map> resultValue = BaseDataServiceHelper.batchAssignWithDetail(ENTITY_SUPPLIER, DEFAULT_ORG_ID, dataIds, new ArrayList(intersectOrgs));
        if (resultValue.isEmpty()){
            result= "";
        }else{
            result = "组织分配错误";
        }
        return result;

    }

    public static Set<Long> intersectionLong(Collection<Long> a, Collection<Long> b) {
        Set<Long> unite = unionLong(a, b);
        Set<Long> cloneFromB = new LinkedHashSet(b);
        unite.removeAll(a);
        cloneFromB.removeAll(unite);
        return cloneFromB;
    }

    public static Set<Long> unionLong(Collection<Long> a, Collection<Long> b) {
        Set<Long> unite = new LinkedHashSet();
        unite.addAll(a);
        unite.addAll(b);
        return unite;
    }

    public class SupplierModel implements Serializable{
        private String number;
        private String name;
        private String group;

        public String getNumber()
        {
            return number;
        }

        public void setNumber(String number)
        {
            this.number = number;
        }

        public String getName()
        {
            return name;
        }

        public void setName(String name)
        {
            this.name = name;
        }

        public String getGroup()
        {
            return group;
        }

        public void setGroup(String group)
        {
            this.group = group;
        }
    }
}
