package com.malk.lemeng.service.impl;

import com.alibaba.fastjson.JSON;
import com.malk.lemeng.service.LMService;
import com.malk.server.aliwork.YDConf;
import com.malk.server.aliwork.YDParam;
import com.malk.server.dingtalk.DDConf;
import com.malk.service.aliwork.YDClient;
import com.malk.service.aliwork.YDService;
import com.malk.service.dingtalk.DDClient;
import com.malk.service.dingtalk.DDClient_Contacts;
import com.malk.service.dingtalk.DDClient_Personnel;
import com.malk.utils.UtilFile;
import com.malk.utils.UtilMap;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class LMImplService implements LMService {

    @Autowired
    private DDClient ddClient;

    @Autowired
    private DDConf ddConf;

    @Autowired
    private DDClient_Contacts ddClient_contacts;

    @Autowired
    private DDClient_Personnel ddClient_personnel;

    @Autowired
    private YDClient ydClient;

    /**
     * 同步花名册信息
     */
    @Override
    public void syncRoster() {

        // 花名册元数据
        List<Map> metaList = (List<Map>) UtilFile.readJsonObjectFromResource("static/json/personnel.json"); // 本地匹配了宜搭组件ID
//        List<Map> metaList = ddClient_personnel.getPersonnelMeta(ddClient.getAccessToken(), ddConf.getAgentId());
        // 同步全量人员
        ddClient_contacts.getDepartmentId_all(ddClient.getAccessToken(), true).forEach(deptId -> {
            List<String> userIds = ddClient_contacts.listDepartmentUserId(ddClient.getAccessToken(), deptId);
            log.info("dept, {}, userIds, {}", deptId, userIds.size());
            if (userIds.size() == 0) {
                return;
            }
            // 员工花名册信息
            ddClient_personnel.getEmployeeInfos(ddClient.getAccessToken(), userIds, ddConf.getAgentId(), null).forEach(employeeInfo -> {
                // 通过元数据字段code, 匹配员工花名册value
                List<Map> employeeField = (List<Map>) employeeInfo.get("field_data_list");
                // 宜搭表单数据
                Map formData = UtilMap.map("employeeField_limrznyp", Arrays.asList(employeeInfo.get("userid"))); // 成员权限
                metaList.forEach(meta -> {
                    boolean isDetail = UtilMap.getBoolean(meta, "detail");
                    List<Map> metaField = (List<Map>) meta.get("field_meta_info_list");
                    Map detail = new HashMap(); // 明细行
                    metaField.forEach(field -> {
                        // 元数据内一些系统字段无 field_code, sys00 基本信息分组下 使用 field_name
                        Optional optional = employeeField.stream().filter(employee -> field.get("field_code").equals(employee.get("field_code")) || employee.get("field_name").equals(field.get("field_name"))).findAny();
                        if (optional.isPresent()) {
                            // 数据组装
                            Map employee = (Map) optional.get();
                            String value = UtilMap.getString(((List<Map>) employee.get("field_value_list")).get(0), "label");
                            log.info("分组 -> {}, 是否明细 -> {}; 字段 -> {}, 值 -> {}", meta.get("group_name"), meta.get("detail"), field.get("field_name"), value);
                            // 值处理
                            if (field.containsKey("comp_id")) {
                                if (isDetail) {
                                    detail.put(field.get("comp_id"), value);
                                } else {
                                    formData.put(field.get("comp_id"), value);
                                }
                            }
                        }
                    });
                    // 明细表
                    if (isDetail && meta.containsKey("comp_id")) {
                        formData.put(meta.get("comp_id"), Arrays.asList(detail));
                    }
                });
                // 宜搭更新 todo 查询同步数据, 代码内匹配, 而不是循环内查询
                YDParam ydParam = YDParam.builder()
                        .searchFieldJson(JSON.toJSONString(UtilMap.map("employeeField_limrznyp", formData.get("employeeField_limrznyp"))))
                        .formUuid("FORM-54C47C335C054FFBAECCA0B92100A341PGD2")
                        .build();
                List<String> formInstIds = (List<String>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_form_id).getData();
                if (formInstIds.size() > 0) {
                    ydParam.setFormInstanceId(formInstIds.get(0));
                    ydParam.setUpdateFormDataJson(JSON.toJSONString(formData));
                    ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
                } else {
                    ydParam.setFormDataJson(JSON.toJSONString(formData));
                    ydClient.operateData(ydParam, YDConf.FORM_OPERATION.create);
                }
            });
        });
    }

    @Autowired
    private YDService ydService;

    private static final int BUDGET_PER = 200;

    /**
     * 同步部门信息
     */
    @Override
    public void syncDepartment() {

        List<Map> budgetList = new ArrayList<>();

        // 部门已同步数据
        List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
                .formUuid("FORM-B6F662B18C3F4D7D855CFE50243394AFQPOH")
                .build());
        // 匹配钉钉通讯录
        List<Long> deptList = ddClient_contacts.getDepartmentId_all(ddClient.getAccessToken(), true, DDConf.TOP_DEPARTMENT);
        for (long deptId : deptList) {
            // 人员为空也同步 [累计到父部门]
            List<String> userIds = ddClient_contacts.listDepartmentUserId(ddClient.getAccessToken(), deptId);
            Map info = ddClient_contacts.getDepartmentInfo(ddClient.getAccessToken(), deptId);
            Map formData = UtilMap.map("textField_lpcff8zu, numberField_lr70cqsl, numberField_lr70cqsk", info.get("name"), info.get("parent_id"), info.get("dept_id"));
            formData.putAll(UtilMap.map("employeeField_lpmbmyaa, departmentSelectField_lpaks312", info.get("dept_manager_userid_list"), Arrays.asList(String.valueOf(info.get("dept_id")))));
            float budget = userIds.size() * BUDGET_PER; // 部门人均
            formData.putAll(UtilMap.map("numberField_lr71bkuj, employeeField_lr71bkui, numberField_lr71mvbk, numberField_lr7yq38c", userIds.size(), userIds, budget, 0));
            // 仅记录当月预算 [记录预算金额]
            Optional optional = dataList.stream().filter(item -> deptId == UtilMap.getLong(item, "numberField_lr70cqsk")).findAny();
            if (optional.isPresent()) {
                formData.put("instanceId", UtilMap.getString((Map) optional.get(), "instanceId"));
                formData.put("radioField_lpaks316", UtilMap.getString((Map) optional.get(), "radioField_lpaks316")); // 记录值
            } else {
                formData.putAll(UtilMap.map("numberField_lpaks318, numberField_lpayajrp, numberField_lpayajrn", 0, 0, 0));
                formData.putAll(UtilMap.map("radioField_lpaks316", "是")); // 默认值
            }
            //formData.putAll(UtilMap.map("numberField_lpaks318, numberField_lpayajrp, numberField_lpayajrn", 0, 0, 0));
            budgetList.add(formData);
        }

        // prd 不存在一人多部门情况, 若是涉及行政归属则手动维护
        List<Map> manualList = ydService.queryFormData_all(YDParam.builder()
                .formUuid("FORM-A192B0134C184B1A84A791F322AA4D60N4F2")
                .build());
        for (Map data : manualList) {
            try {
                String userId = String.valueOf(UtilMap.getList(data, "employeeField_lroz3y2w_id").get(0));
                Map srcDpet = budgetList.stream().filter(item -> UtilMap.getList(item, "employeeField_lr71bkui").contains(userId)).findAny().get();
                updateBalance(srcDpet, -BUDGET_PER, -1); // 去除原部门个人金额

                boolean multi = StringUtils.isNotBlank(UtilMap.getString(data, "numberField_lroz3y37"));
                if (multi) {
                    Map curDpet = budgetList.stream().filter(item -> data.get("numberField_lroz3y37").equals(item.get("numberField_lr70cqsk"))).findAny().get();
                    updateBalance(curDpet, BUDGET_PER / 2, 0.5f); // 累加部门2个人金额一半
                }
                Map curDpet = budgetList.stream().filter(item -> data.get("numberField_lr70cqsk").equals(item.get("numberField_lr70cqsk"))).findAny().get();
                updateBalance(curDpet, multi ? BUDGET_PER / 2 : BUDGET_PER, multi ? 0.5f : 1f); // 累加部门1个人金额
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }

        // prd 累计子节点
        for (Map formData : budgetList) {
            accBudget(formData, budgetList);
        }
        // prd 大区拆分一半
        List<Map> halfList = ydService.queryFormData_all(YDParam.builder()
                .formUuid("FORM-1393DC7A16424FC1BC84146C88586F91Q012")
                .build());
        for (Map dept : halfList) {
            try {
                // 顶部公司
                Long deptId = UtilMap.getLong(dept, "numberField_lr70cqsk");
                Map pData = budgetList.stream().filter(item -> deptId == UtilMap.getLong(item, "numberField_lr70cqsk")).findAny().get();
                // 下属公司
                List<Long> subList = ddClient_contacts.getDepartmentId_all(ddClient.getAccessToken(), false, deptId);
                for (Long dId : subList) {
                    Map dData = budgetList.stream().filter(item -> dId == UtilMap.getLong(item, "numberField_lr70cqsk")).findAny().get();
                    float budget = UtilMap.getFloat(dData, "numberField_lr71mvbk");
                    if (budget <= 0) {
                        continue;
                    }
                    budget = budget / 2;
                    float quota = UtilMap.getFloat(dData, "numberField_lr71bkuj") / 2;
                    updateBalance(dData, -budget, -quota);      // 删除原余额一半
                    updateBalance(pData, budget, quota);        // 累计新余额一半
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }

        // Upsert操作, 记录当月预算
        for (Map formData : budgetList) {
            String formInstanceId = UtilMap.getString(formData, "instanceId");
            YDParam ydParam = YDParam.builder()
                    .formUuid("FORM-B6F662B18C3F4D7D855CFE50243394AFQPOH")
                    .formDataJson(JSON.toJSONString(formData))
                    .updateFormDataJson(JSON.toJSONString(formData))
                    .build();
            YDConf.FORM_OPERATION operation = YDConf.FORM_OPERATION.create;
            if (StringUtils.isNotBlank(formInstanceId)) {
                ydParam.setFormInstanceId(formInstanceId);
                operation = YDConf.FORM_OPERATION.update;
            }
            ydClient.operateData(ydParam, operation);
        }
    }

    // 非子阶段归属到上一层部门
    private void accBudget(Map formData, List<Map> dataList) {
        if ("否".equals(formData.get("radioField_lpaks316"))) {
            try {
                Map pData = dataList.stream().filter(item -> formData.get("numberField_lr70cqsl").equals(item.get("numberField_lr70cqsk"))).findAny().get();
                float budget = UtilMap.getFloat(formData, "numberField_lr71mvbk");
                float quota = UtilMap.getFloat(formData, "numberField_lr71bkuj");
                updateBalance(formData, -budget, -quota);   // 删除原余额
                updateBalance(pData, budget, quota);        // 累计新余额
                accBudget(pData, dataList);                 // 是递归出口
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    /// 涉及行政归属, 拆分规则
    private void updateBalance(Map item, float budget, float quota) {
        item.put("numberField_lr7yq38c", UtilMap.getFloat(item, "numberField_lr7yq38c") + budget);                                                       // 调差金额
        item.put("numberField_lr71mvbk", UtilMap.getFloat(item, "numberField_lr71mvbk") + budget); // 当月预计预算
        item.put("numberField_lr71bkuj", UtilMap.getFloat(item, "numberField_lr71bkuj") + quota);  // 部门人数
    }

    /**
     * 部门预算统计
     */
    @Override
    @Synchronized
    public void calcBudget() {

        // 部门已同步数据
        List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
                .formUuid("FORM-B6F662B18C3F4D7D855CFE50243394AFQPOH")
                .build());
        dataList.forEach(item -> {
            int budget = UtilMap.getInt(item, "numberField_lr71mvbk");
            // 清空当月余额, 避免重复调用
            item.put("numberField_lr71mvbk", 0);
            item.put("numberField_lpaks318", UtilMap.getFloat(item, "numberField_lpaks318") + budget);
            item.put("numberField_lpayajrn", UtilMap.getFloat(item, "numberField_lpayajrn") + budget);
            // 非常规组件数据处理
            item.putAll(UtilMap.map("employeeField_lr71bkui, departmentSelectField_lpaks312", item.get("employeeField_lr71bkui_id"), item.get("departmentSelectField_lpaks312_id")));
            ydClient.operateData(YDParam.builder()
                    .formInstanceId(UtilMap.getString(item, "instanceId"))
                    .updateFormDataJson(JSON.toJSONString(item))
                    .build(), YDConf.FORM_OPERATION.update);
        });
    }

    /// test
    @Override
    public void test() {
        ddClient_personnel.getPersonnelMeta(ddClient.getAccessToken(), ddConf.getAgentId());
    }
}
