package yem.base.common.module.meta.report;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import kd.bos.algo.*;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
import kd.bos.entity.report.AbstractReportListDataPlugin;
import kd.bos.entity.report.FilterInfo;
import kd.bos.entity.report.ReportQueryParam;
import kd.bos.orm.ORM;
import kd.sdk.plugin.Plugin;
import yem.base.common.utils.HttpHelper;
import yem.base.common.utils.TokenUtil;
import yem.base.common.utils.YEM;

import java.util.*;

/**
 * 数据结构比对
 *
 * @author longh
 * @description 报表查询插件
 * @date 2023年12月27日
 */
public class MetaCompareRptQuery extends AbstractReportListDataPlugin implements Plugin {
    private static final List<String> fieldKeys = new ArrayList<>();
    private String domainContextUrl = "";
    private TokenUtil tokenUtil;

    private static Field[] getFormFields() {
        fieldKeys.clear();
        fieldKeys.add("yem_parent1");
        fieldKeys.add("yem_entity1");
        fieldKeys.add("yem_number1");
        fieldKeys.add("yem_fullnumber1");
        fieldKeys.add("yem_alias1");
        fieldKeys.add("yem_name1");
        fieldKeys.add("yem_fullname1");
        fieldKeys.add("yem_datatype1");
        fieldKeys.add("yem_aliastype1");
        fieldKeys.add("yem_datatype_key1");
        fieldKeys.add("yem_basedatakey1");

        fieldKeys.add("yem_parent2");
        fieldKeys.add("yem_entity2");
        fieldKeys.add("yem_number2");
        fieldKeys.add("yem_fullnumber2");
        fieldKeys.add("yem_alias2");
        fieldKeys.add("yem_name2");
        fieldKeys.add("yem_fullname2");
        fieldKeys.add("yem_datatype2");
        fieldKeys.add("yem_aliastype2");
        fieldKeys.add("yem_datatype_key2");
        fieldKeys.add("yem_basedatakey2");

        fieldKeys.add("yem_change");

        List<Field> fields = new ArrayList<>();
        for (String key : fieldKeys) {
            fields.add(new Field(key, DataType.StringType));
        }
        return fields.toArray(new Field[0]);
    }

    @Override
    public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
        FilterInfo filterInfo = reportQueryParam.getFilter();
        DynamicObject yem_fentityobj = filterInfo.getDynamicObject("yem_fentityobj");
        String entityKey = yem_fentityobj == null ? "" : yem_fentityobj.getString("number");
        DynamicObject yem_fentityobj1 = filterInfo.getDynamicObject("yem_fentityobj1");
        String entityKey_s = yem_fentityobj1 == null ? "" : yem_fentityobj1.getString("number");
        boolean onlyChanged = filterInfo.getBoolean("yem_onlychanged");

        initApiInfo(filterInfo);
        //"yem_purchaseorder"
        //"yem_dt_purchaseorder"
        Map<String, Map<String, Map<String, Object>>> allData1 = YEM.isEmpty(entityKey_s) ? getMapsApi(entityKey) : getMaps(entityKey_s);
        Map<String, Map<String, Map<String, Object>>> allData2 = getMaps(entityKey);

        Field[] formFields = getFormFields();
        Collection<Object[]> collection = new ArrayList<>();
        for (String entityNumber : allData2.keySet()) {
            Map<String, Map<String, Object>> vMap2 = allData2.get(entityNumber);
            if (allData1.containsKey(entityNumber)) {
                Map<String, Map<String, Object>> vMap1 = allData1.get(entityNumber);
                for (String number : vMap2.keySet()) {
                    Map<String, Object> map2 = vMap2.get(number);
                    if (vMap1.containsKey(number)) {
                        Map<String, Object> map1 = vMap1.get(number);
                        addData(collection, map1, map2);
                        vMap1.remove(number);
                    } else {
                        addData(collection, null, map2);
                    }
                }
                for (String number : vMap1.keySet()) {
                    Map<String, Object> map1 = vMap1.get(number);
                    addData(collection, map1, null);
                }
                allData1.remove(entityNumber);
            } else {
                for (String number : vMap2.keySet()) {
                    Map<String, Object> map2 = vMap2.get(number);
                    addData(collection, null, map2);
                }
            }
        }
        for (String entityNumber : allData1.keySet()) {
            Map<String, Map<String, Object>> vMap1 = allData1.get(entityNumber);
            for (String number : vMap1.keySet()) {
                Map<String, Object> map1 = vMap1.get(number);
                addData(collection, map1, null);
            }
        }
        DataSet dataSet = Algo.create(this.getClass().getName()).createDataSet(collection, new RowMeta(formFields));
        if (onlyChanged) {
            dataSet = dataSet.where("yem_change is not null and yem_change <> ''");
        }
        return dataSet;
    }

    private void addData(Collection<Object[]> collection, Map<String, Object> map1, Map<String, Object> map2) {
        int i = 0;
        Object[] row = new Object[fieldKeys.size()];

        row[i++] = map1 == null ? "" : map1.get("yem_parent2");
        row[i++] = map1 == null ? "" : map1.get("yem_entity2");
        row[i++] = map1 == null ? "" : map1.get("yem_number2");
        row[i++] = map1 == null ? "" : map1.get("yem_fullnumber2");
        row[i++] = map1 == null ? "" : map1.get("yem_alias2");
        row[i++] = map1 == null ? "" : map1.get("yem_name2");
        row[i++] = map1 == null ? "" : map1.get("yem_fullname2");
        row[i++] = map1 == null ? "" : map1.get("yem_datatype2");
        row[i++] = map1 == null ? "" : map1.get("yem_aliastype2");
        row[i++] = map1 == null ? "" : map1.get("yem_aliastype2");
        row[i++] = map1 == null ? "" : map1.get("yem_basedatakey2");

        row[i++] = map2 == null ? "" : map2.get("yem_parent2");
        row[i++] = map2 == null ? "" : map2.get("yem_entity2");
        row[i++] = map2 == null ? "" : map2.get("yem_number2");
        row[i++] = map2 == null ? "" : map2.get("yem_fullnumber2");
        row[i++] = map2 == null ? "" : map2.get("yem_alias2");
        row[i++] = map2 == null ? "" : map2.get("yem_name2");
        row[i++] = map2 == null ? "" : map2.get("yem_fullname2");
        row[i++] = map2 == null ? "" : map2.get("yem_datatype2");
        row[i++] = map2 == null ? "" : map2.get("yem_aliastype2");
        row[i++] = map2 == null ? "" : map2.get("yem_aliastype2");
        row[i++] = map2 == null ? "" : map2.get("yem_basedatakey2");

        String change = "";
        if (map1 == null) {
            change = "A";//新增
        } else if (map2 == null) {
            change = "B";//删除
        } else if (!map1.get("yem_datatype2").equals(map2.get("yem_datatype2"))) {
            change = "C";//类型不同
        }
        row[i++] = change;

        collection.add(row);
    }

    private Map<String, Map<String, Map<String, Object>>> getMaps(String entityKey) {
        //Map<实体标识, Map<实体字段标识, Map<字段标识, 值>>>
        Map<String, Map<String, Map<String, Object>>> allAata = new LinkedHashMap<>();
        if (YEM.isEmpty(entityKey)) {
            return allAata;
        }
        DataSet dataSet1 = DataDictionaryRptQuery.queryDataBill(entityKey);
        DynamicObjectCollection dynamicObjects = ORM.create().toPlainDynamicObjectCollection(dataSet1);
        for (DynamicObject obj : dynamicObjects) {
            String number = (String) obj.get("yem_number2");//编码
            String fullnumber = (String) obj.get("yem_fullnumber2");//全编码
            String entityNumber = "head";
            if (fullnumber.contains(".")) {
                entityNumber = YEM.substringBeforeLast(fullnumber, ".");
            }
            Map<String, Map<String, Object>> vMap;
            if (allAata.containsKey(entityNumber)) {
                vMap = allAata.get(entityNumber);
            } else {
                vMap = new LinkedHashMap<>();
            }
            Map<String, Object> map = new HashMap<>();
            DataEntityPropertyCollection properties = obj.getDynamicObjectType().getProperties();
            for (IDataEntityProperty property : properties) {
                String key = property.getName();
                map.put(key, obj.get(key));
            }
            vMap.put(number, map);
            allAata.put(entityNumber, vMap);
        }
        return allAata;
    }

    private Map<String, Map<String, Map<String, Object>>> getMapsApi(String entityKey) {
        //Map<实体标识, Map<实体字段标识, Map<字段标识, 值>>>
        Map<String, Map<String, Map<String, Object>>> allAata = new LinkedHashMap<>();
        if (YEM.isEmpty(entityKey)) {
            return allAata;
        }
        String requestData;
        try {
            requestData = getRequestData(entityKey);
            if (YEM.isNotEmpty(requestData)) {
                JSONObject data = JSONObject.parseObject(requestData);
                JSONArray dynamicObjects = data.getJSONArray("data");
                for (int i = 0; i < dynamicObjects.size(); i++) {
                    JSONObject obj = dynamicObjects.getJSONObject(i);
                    String number = (String) obj.get("yem_number2");//编码
                    String fullnumber = (String) obj.get("yem_fullnumber2");//全编码
                    String entityNumber = "head";
                    if (fullnumber.contains(".")) {
                        entityNumber = YEM.substringBeforeLast(fullnumber, ".");
                    }
                    Map<String, Map<String, Object>> vMap;
                    if (allAata.containsKey(entityNumber)) {
                        vMap = allAata.get(entityNumber);
                    } else {
                        vMap = new LinkedHashMap<>();
                    }
                    Map<String, Object> map = new HashMap<>();
                    for (String key : obj.keySet()) {
                        map.put(key, obj.get(key));
                    }
                    vMap.put(number, map);
                    allAata.put(entityNumber, vMap);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return allAata;
        }
        return allAata;
    }

    private String getRequestData(String entityKey) throws Exception {
        Map<String, String> header = new HashMap<>();
        header.put("access_token", tokenUtil.getAccessToken());
        JSONObject param = new JSONObject();
        param.put("billKey", entityKey);
        String url = domainContextUrl + "/kapi/app/yem_basiccore/BillDataGetApi";
        return HttpHelper.httpPost(url, header, param.toJSONString());
    }

    private void initApiInfo(FilterInfo filterInfo) {
        domainContextUrl = filterInfo.getString("yem_url");
        String appId = filterInfo.getString("yem_appid");
        String appSecuret = filterInfo.getString("yem_appsecuret");
        String tenantid = filterInfo.getString("yem_tenantid");
        String accountId = filterInfo.getString("yem_accountid");
        String user = filterInfo.getString("yem_user");
        String usertype = filterInfo.getString("yem_usertype");
        tokenUtil = new TokenUtil(domainContextUrl, appId, appSecuret, tenantid, accountId, user, usertype);
    }

}