package com.malk.hake.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.malk.hake.service.HKClient_ML;
import com.malk.server.aliwork.YDConf;
import com.malk.server.aliwork.YDParam;
import com.malk.server.common.McException;
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.DDService;
import com.malk.utils.*;
import lombok.SneakyThrows;
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.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class HKImplClient_ML implements HKClient_ML {

    @Autowired
    private YDClient ydClient;

    // monitor接口ip [fixme 马哈使用test环境, 新建环境变量没有mjava继承文件
    String _getEnvApi(String path) {
        if (UtilEnv.getActiveProfile().equals(UtilEnv.ENV_TEST)) {
            return "http://172.19.10.4:10002/api/public" + path;
        }
//        return "http://hawkfiltration.fortiddns.com:10001/api/public" + path; // 10001 测试
        return "http://hawkfiltration.fortiddns.com:10002/api/public" + path; // 10002 生产
    }

    private Map MATE;

    private Map _getMeta() {
        if (ObjectUtil.isNull(MATE)) {
            MATE = (Map) UtilFile.readJsonObjectFromResource("static/json/form_ml.json"); // 本地匹配宜搭组件ID
        }
        return MATE;
    }

    /**
     * 创建/更新数据
     */
    private String upsertData(String code, Map data) {
        // 组织单据数据
        Map meta = _getMeta();
        Map<String, ?> component = (Map) ((Map) meta.get(code)).get("compIds");
        Map formData = UtilMap.empty();
        for (String key : component.keySet()) {
            if (key.startsWith("employeeField_")) {
                // getString, 避免 [null] 数据类型
                formData.put(key, Arrays.asList(UtilMap.getString(data, (String) component.get(key))));
            } else if (key.startsWith("tableField_")) {
                List<Map> rows = (List<Map>) data.get("rows");
                List<Map> details = new ArrayList<>();
                Map<String, String> compIds = (Map) component.get(key);
                for (Map row : rows) {
                    Map detail = UtilMap.empty();
                    for (String prop : compIds.keySet()) {
                        detail.put(prop, row.get(compIds.get(prop)));
                    }
                    details.add(detail);
                }
                formData.put(key, details);
            } else if (key.startsWith("dateField_")) {
                String date = String.valueOf(data.get(component.get(key)));
                if (StringUtils.isNotBlank(date)) {
                    formData.put(key, UtilDateTime.parse(date, "yyyy/MM/dd").getTime());
                }
            } else {
                Object value = data.get(component.get(key));
                formData.put(key, value);
            }
        }
        // 发起人匹配规则
        String userId = _getUserId(code, meta, data);
        YDConf.FORM_OPERATION operation = YDConf.FORM_OPERATION.start;
        String processCode = String.valueOf(((Map) meta.get(code)).get("processCode"));
        if (UtilString.isBlankCompatNull(processCode)) {
            operation = YDConf.FORM_OPERATION.create;
        }
        String formInstanceId = UtilMap.getString(data, "instanceId");
        YDParam ydParam = YDParam.builder()
                .formUuid(String.valueOf(((Map) meta.get(code)).get("formUuid")))
                .processCode(processCode)
                .userId(userId)
                .formDataJson(JSON.toJSONString(formData))
                .updateFormDataJson(JSON.toJSONString(formData))
                .useLatestVersion(true)
                .build();
        // 匹配更新机制: Upsert操作
        if (StringUtils.isNotBlank(formInstanceId)) {
            ydParam.setFormInstanceId(formInstanceId);
            operation = YDConf.FORM_OPERATION.update;
        }
        Object result = ydClient.operateData(ydParam, operation);
        return StringUtils.isNotBlank(formInstanceId) ? formInstanceId : (String) result;
    }

    /// 发起人处理
    String _getUserId(String code, Map meta, Map data) {
        String userId = String.valueOf(data.get(String.valueOf(((Map) meta.get(code)).get("creator"))));
        // 报价单
        if ("BJ".equals(code)) {
            if (Arrays.asList("样品", "大货").contains(data.get("quoteType"))) {
                userId = String.valueOf(data.get("dtOurReferencePersonId"));
            } else {
                userId = String.valueOf(data.get("dtSellerPersonId"));
            }
        }
        if (UtilString.isBlankCompatNull(userId)) {
            userId = YDConf.PUB_ACCOUNT;
        }
        return userId;
    }

    @Autowired
    private YDConf ydConf;

    /**
     * 通用流程发起
     */
    @SneakyThrows
    @Override
    public Map<String, Object> startProcess(String code, Map data) {
        String instanceId = upsertData(code, data);
        Map meta = _getMeta();
        // 回传钉钉单据号
        Thread.sleep(800);
        Map form = ydClient.queryData(YDParam.builder()
                .formInstanceId(String.valueOf(instanceId))
                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
        String url = "https://pxi03f.aliwork.com/" + ydConf.getAppType() + "/processDetail?procInsId=" + instanceId;
        return UtilMap.map("ddProcessId, dtNumber, dtUrl", instanceId, form.get(meta.get(code + "_RC")), url);
    }

    @Autowired
    private DDClient ddClient;

    @Autowired
    private DDClient_Contacts ddClient_contacts;

    @Autowired
    private DDService ddService;

    private static final String AUTH = "bbb76928-a9db-42fa-ac83-cc9a2ed75162";

    /**
     * 通用审批回调 [区分类型, 宜搭提示不同报错信息]
     */
    @Override
    public void callbackProcess(Map data) {

        // 拒绝审批意见必填校验
        McException.assertParamException_Null(data, "Result");
        // prd 4.17 取消拒绝校验, 统一返回 [审核人xxx拒绝], monitor通过活动跳转
        //if ("0".equals(data.get("Result"))) {
        // McException.assertParamException_Null(data, "Remark");
        //}
        // 回调monitor审批信息
        data.put("Url", "https://pxi03f.aliwork.com/" + ydConf.getAppType() + "/processDetail?procInsId=" + data.get("DdProcessId"));
        data.put("ApprovalDate", UtilDateTime.formatLocalDateTime(LocalDateTime.now()));
        Map UserInfo = ddClient_contacts.getUserInfoById(ddClient.getAccessToken(), String.valueOf(data.get("Approver")));
        // prd 4.17 取消拒绝校验, 统一返回 [审核人xxx拒绝], monitor通过活动跳转
        if ("0".equals(data.get("Result")) && !data.containsKey("Remark")) {
            data.put("Remark", "审批人 【" + UserInfo.get("name") + "】拒绝");
        }
        data.put("Approver", String.valueOf(UserInfo.get("name")));
        log.info("审批回调, {}", JSON.toJSONString(data));
        // prd: 通过 http status 判定, 200 即为成功
        String rsp = UtilHttp.doPost(_getEnvApi("/Approval"), UtilMap.map("Authorization", AUTH), UtilMap.map("Code", data.get("Code")), data);
        Map result = (Map) JSON.parse(rsp);
        McException.assertException(result.containsKey("errorMsg"), String.valueOf(result.get("status")), String.valueOf(result.get("errorMsg")), "Monitor");
    }

    /**
     * 通讯录同步
     */
    @Override
    @Synchronized
    public void syncContact() {

        // prd: 非全量同步: 马来部门
//        List<Long> deptList = UtilList.asList(989604056L, 988784619L); // 马来/劳工 product
        List<Long> deptList = UtilList.asList(989604056L); // 马来/劳工 product
        // prd: 10.21 马来没有三级部门, 只处理二级部门，一级就是大公司
        ddClient_contacts.getDepartmentId_all(ddClient.getAccessToken(), false, deptList.get(0)).forEach(deptList::add);

        for (long deptId : deptList) {
            List<String> userIds = ddClient_contacts.listDepartmentUserId(ddClient.getAccessToken(), deptId);
            if (userIds.size() == 0) {
                continue;
            }
            String dpetCascade = ddService.getUserDepartmentHierarchyJoin(ddClient.getAccessToken(), userIds.get(0), "-");
            String deptName = UtilMap.getString(ddClient_contacts.getDepartmentInfo(ddClient.getAccessToken(), deptId), "name");
            for (String userId : userIds) {
                Map userInfo = ddClient_contacts.getUserInfoById(ddClient.getAccessToken(), userId);
                Map data = UtilMap.map("employeeNumber, employeeName, dtPersonId, lastName", userInfo.get("job_number"), userInfo.get("name"), userInfo.get("userid"), userInfo.get("title"));
                // prd: 手机号花名册未展示, 因此添加判空, 避免覆盖Monitor
                if (StringUtils.isNotBlank(String.valueOf(userInfo.get("mobile")))) {
                    data.put("mobilePhone", userInfo.get("mobile"));
                }
                if (userInfo.containsKey("org_email")) {
                    data.put("email", userInfo.get("org_email"));
                }
                long hiredDate = new Date().getTime();
                if (userInfo.containsKey("hired_date")) {
                    hiredDate = UtilMap.getLong(userInfo, "hired_date");
                }
                /// prd 10.21 马来入职必填的, 默认为入职日期, 若为空则取值当前日期
                data.put("employeeStartDate", UtilDateTime.formatDate(new Date(hiredDate)));
                data.put("employeeDept", deptName);
                data.put("dtDepts", dpetCascade);
                data.put("dtPersonGroup", "");
                log.info("同步人员, {}", JSON.toJSONString(UtilMap.map("employees", Arrays.asList(data))));
                _syncContact(data, userId);
            }
        }

        // 离职人员同步
        Date sDate = UtilDateTime.convertToDateFromLocalDateTime(LocalDateTime.now().minusDays(1));
        List<Map<String, String>> maps = ddClient_contacts.getLeaveEmployeeRecords(ddClient.getAccessToken(), sDate, null);
        for (Map<String, String> map : maps) {
            // prd 钉钉离职数据获取不到工号, 通过99999 monitor判断, 若存在则更新部门, 负责忽略
            Map data = UtilMap.map("employeeNumber, employeeName, dtPersonId, mobilePhone, employeeDept", "99999", map.get("name"), map.get("userId"), map.get("mobile"), "离职");
            data.put("employeeFinishDate", map.get("leaveTime").split("T")[0]);
            _syncContact(data, map.get("userId"));
            log.info("离职人员, {}", JSON.toJSONString(UtilMap.map("employees", Arrays.asList(data))));
        }
    }

    /// 员工信息写入monitor
    void _syncContact(Map data, String userId) {

        // prd: 通过 http status 判定, 200 即为成功
        String rsp = UtilHttp.doPost(_getEnvApi("/EmployeeImport"), UtilMap.map("Authorization", AUTH), null, UtilMap.map("employees", Arrays.asList(data)));
        Map result = (Map) JSON.parse(rsp);
        if (UtilList.isNotEmpty(UtilMap.getList(result, "fail"))) {
            result = (Map) UtilMap.getList(result, "fail").get(0); // 单条同步, 记录错误人员
        }
        //McException.assertException(result.containsKey("msg"), String.valueOf(result.get("status")), String.valueOf(result.get("msg")), "Monitor");
        if (result.containsKey("msg")) {
            ydClient.operateData(YDParam.builder()
                    .formUuid("FORM-49C2AC35492D4D69BF98036B1B756105MT59")
                    .formDataJson(JSON.toJSONString(UtilMap.map("dateField_lo47byyd, employeeField_lo47byyj, textareaField_lo47byyo, textareaField_lo47sanj", new Date().getTime(), userId, result, data)))
                    .build(), YDConf.FORM_OPERATION.create);
        }
    }

    @Autowired
    private YDService ydService;

    /**
     * 付款数据同步
     */
    @Override
    public void syncMonitor(String code, Map data) {

        McException.assertAccessException(!Arrays.asList("FKSQ", "YFKSQ").contains(code), "单据编码未匹配");
        boolean isYF = "YFKSQ".equals(code);

        // prd 25.01.06 预付款订单数据支持筛选: 采购订单号、供应商号、供应商名称的筛选条件，如果为空就查询所有的数据，有值就查询出对应值的数据
        Map body = UtilMap.empty();
        if (isYF) {
            UtilMap.putAll(body, data);
        }

        String rsp = UtilHttp.doPost(_getEnvApi(isYF ? "/PrePayment" : "/Payment"), UtilMap.map("Authorization", AUTH), null, UtilMap.empty());
        Map result = (Map) JSON.parse(rsp);
        List<Map> dataList = (List<Map>) UtilMap.getList(result, isYF ? "orders" : "rows");
        log.info("付款数据同步, {} {}", code, dataList.size());
        // prd: 通过 http status 判定, 200 即为成功
        for (Map row : dataList) {
            Map search = null;
            if (isYF) {
                search = YDConf.searchCondition_TextFiled("textField_lnmyiqan", UtilMap.getString(row, "orderNumber"), "eq");
            } else {
                search = YDConf.searchCondition_TextFiled("textField_lnmzbyzu", UtilMap.getString(row, "invoiceNumber"), "eq");
            }
            // 匹配是否新增
            List<Map> formList = ydService.queryFormData(isYF ? "FORM-98BF1EE731CD48078FEA0701C5F08E73PKQU" : "FORM-7DA9C030A3E84689AADA23BA6BAC435DVWDM", JSON.toJSONString(Arrays.asList(search)));
            if (formList.size() == 0) {
                // 宜搭付款控制字段
                row.put("status", "否");       // 反馈中
                row.put("payed", 0);           // 已付款
            } else {
                Map record = formList.get(0);
                row.put("status", record.get("radioField_ls3ddkie"));       // 反馈中
                row.put("payed", record.get("numberField_ls3ddkif"));       // 已付款
                row.put("instanceId", record.get("instanceId"));
            }
            upsertData(code, row);
        }
    }
}
