package com.malk.aiwei.controller;

/**
 * 错误抛出与拦截详见 CatchException
 */

import com.alibaba.fastjson.JSON;
import com.malk.aiwei.service.AWClint;
import com.malk.aiwei.service.AWYDClient;
import com.malk.delegate.McDelegate;
import com.malk.server.aliwork.YDConf;
import com.malk.server.aliwork.YDParam;
import com.malk.server.common.McException;
import com.malk.server.common.McR;
import com.malk.server.dingtalk.DDConf;
import com.malk.server.teambition.TBConf;
import com.malk.service.aliwork.YDClient;
import com.malk.service.aliwork.YDService;
import com.malk.service.teambition.TBClient;
import com.malk.utils.UtilExcel;
import com.malk.utils.UtilMap;
import com.malk.utils.UtilServlet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Slf4j
@RestController
@RequestMapping
public class TBxYDController {

    @Autowired
    private AWClint awClint;

    /**
     * 交付物审批回调
     */
    @PostMapping("approved")
    McR approve(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("交付物审批回调, {}", data);
        McException.assertParamException_Null(data, "projectId, taskId, creatorId, approve");

        awClint.approved(data);
        return McR.success();
    }

    /**
     * 检查项check回调
     */
    @PostMapping("checked")
    McR check(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("检查项check回调, {}", data);
        McException.assertParamException_Null(data, "taskId, formInstId");

        awClint.checked(data);
        return McR.success();
    }

    /**
     * 选项卡渲染获取详情
     */
    @PostMapping("load-check")
    public Map details(String taskId) {

        log.info("选项卡渲染, {}", taskId);
        String result = UtilMap.getString(awClint.doCheck(taskId, true), "result");
        String strJson = "{\"version\":\"1.0.0\",\"template\":{\"status\":\"#variables.status#\",\"toolbar\":[{\"label\":\"成功\",\"type\":\"text\",\"visible\":\"#variables.isDetailVisible#\",\"payload\":\"#variables.detailURL#\"}]},\"data\":[{\"itemId\":\"61b80257e1fe2200410c8ecd\",\"avatarUrl\":\"\",\"title\":\"xxxxx\",\"description\":\"\"}],\"variables\":{\"userId\":\"5bdc085d60bcef000146634f\",\"taskId\":\"\",\"status\":\"\",\"primaryLabel\":\"详情\",\"itemURL\":\"\",\"detailURL\":\"\",\"createURL\":\"\",\"createPlanTimeLabel\":\"\",\"createPlanTimeURL\":\"\",\"editURL\":\"\",\"removeURL\":\"\",\"isItemVisible\":true,\"isDetailVisible\":true,\"isCreatePlanTimeVisible\":true,\"isPrimaryVisible\":true,\"isEditVisible\":true,\"isRemoveVisible\":true}}";
        strJson = strJson.replace("xxxxx", result);
        return (Map) JSON.parse(strJson);
    }


    /**
     * 自定义审批字段模板渲染
     */
    @GetMapping("field-template")
    public List<Map> template(String nonce, long timestamp, String appId, String sign, String organizationId, String projectId) {

        log.info("自定义审批字段模板渲染, {}, {}, {}, {}, {}, {}", nonce, new Date(timestamp), appId, sign, organizationId, projectId);

        List<Map> templateIds = new ArrayList<>();
        templateIds.add(UtilMap.map("id, title, payload", "FORM-FBC1A390B4C348089020C763938A6F54RUNY", "交付物审批", UtilMap.map("templateId", "FORM-FBC1A390B4C348089020C763938A6F54RUNY")));
        templateIds.add(UtilMap.map("id, title, payload", "FORM-F6B54810EBA84F7AA9AC82EE1D8AE4D3GPKR", "预检项确认", UtilMap.map("templateId", "FORM-F6B54810EBA84F7AA9AC82EE1D8AE4D3GPKR")));
        return templateIds;
    }


    /**
     * 检查项发起
     */
    @PostMapping("do-check")
    McR doCheck(String taskId) {

        log.info("检查项发起, {}", taskId);
        return McR.success(awClint.doCheck(taskId, false));
    }

    /**
     * 交付物审批
     */
    @PostMapping("do-approve")
    McR doApprove(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("交付物审批, {}", data);
        Map formData = awClint.doApprove(data, UtilMap.getBoolean(data, "isChange"));
        return McR.success(formData);
    }

    /**
     * 交付物变更发起
     */
    @PostMapping("change-approve")
    McR changeApprove(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("交付物变更发起, {}", data);

        // prd 618 通过任务扩展按钮变更情况, 提交后再触发审批回写
        if (UtilMap.getBoolean(data, "isChange")) {
            awClint.changeApprove(UtilMap.getString(data, "taskId"), UtilMap.getString(data, "formInstId"), UtilMap.getString(data, "title"));
        }
        return McR.success();
    }

    /**
     * 通过模板创建项目
     */
    @PostMapping("project/create")
    McR createProject(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("通过模板创建项目, {}", data);
        McException.assertParamException_Null(data, "projectCode");
        String templateId = UtilMap.getString(data, "templateId");
        if (data.containsKey("manual")) {
            awClint.createProject(UtilMap.getString(data, "projectCode"), templateId);
        } else {
            // ppExt: 宜搭数据创建后, 以及客户系统同步到主数据有时间差, 做延迟代理 10s
            mcDelegate.setTimeout(() -> {
                awClint.createProject(UtilMap.getString(data, "projectCode"), templateId);
            }, 10000);
        }
        return McR.success();
    }

    /**
     * 分配项目角色
     */
    @PostMapping("project/role")
    McR updateRoleProject(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("分配项目角色, {}", data);
        McException.assertParamException_Null(data, "projectId", "trNode");

        List<String> trNodes = (List<String>) JSON.parse(UtilMap.getString(data, "trNode"));
        awClint.updateProjectRole(UtilMap.getString(data, "projectId"), trNodes, UtilMap.getString(data, "production"), UtilMap.getString(data, "version"));
        return McR.success();
    }

    /**
     * 删除前后置依赖
     */
    @PostMapping("project/remove/dependencies")
    McR removeDependencies(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("删除前后置依赖, {}", data);
        McException.assertParamException_Null(data, "projectId", "trNode");

        awClint.removeDependencies(UtilMap.getString(data, "projectId"), (List<String>) JSON.parse(UtilMap.getString(data, "trNode")));
        return McR.success();
    }

    /**
     * 手动触发, 同步项目主数据
     */
    @PostMapping("project/sync")
    McR syncProject() {
        awClint.syncProject(null);
        return McR.success();
    }

    /**
     * 手动触发, 同步预检项
     */
    @PostMapping("check/sync")
    McR syncCheck(int type) {
        awClint.syncCheckList(type);
        return McR.success();
    }

    /**
     * 项目主数据增量更新
     */
    @PostMapping("project/update")
    McR updateProject(HttpServletRequest request) {
        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("项目主数据增量更新, {}", data);

        // ppExt: 宜搭数据创建后, 以及客户系统同步到主数据有时间差, 做延迟代理 10s
        mcDelegate.setTimeout(() -> {
            // 多项目变更（项目成员变更） ppExt: 自动化通过公式获取子表字段，接口取不到。目前先通过传递实例ID，进行查询
            if (data.containsKey("formInstId")) {
                Map formData = ydClient.queryData(YDParam.builder()
                        .formInstanceId(UtilMap.getString(data, "formInstId"))
                        .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
                for (Map row : (List<Map>) UtilMap.getList(formData, "tableField_lqovv8at")) {
                    awClint.updateProject(UtilMap.getString(row, "textField_lqovv8ax"));
                }
            }
            // 单项目变更（项目号变更）
            if (data.containsKey("projectCode")) {
                awClint.updateProject(UtilMap.getString(data, "projectCode"));
            }
        }, 10000);
        return McR.success();
    }

    /**
     * 手动触发, 同步CRM基线数据
     */
    @PostMapping("crm/sync")
    McR syncCRM(HttpServletRequest request) {
        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("同步CRM基线数据, {}", data);

        if (data.containsKey("projectId")) {
            awClint.syncBaseLineForCRM(UtilMap.getString(data, "projectId"));
        } else {
            awClint.syncBaseLineForCRM();
        }
        return McR.success();
    }

    /**
     * 手动触发, 批量修改项目角色
     */
    @PostMapping("batch/update")
    McR batchUpdate(HttpServletRequest request) {
        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("批量修改项目角色, {}", data);
        McException.assertParamException_Null(data, "fieldName, preName, modifyName");

        String fieldName = UtilMap.getString(data, "fieldName");
        String preName = UtilMap.getString(data, "preName");
        String modifyName = UtilMap.getString(data, "modifyName");
        awClint.batchUpdate(fieldName, preName, modifyName, UtilMap.getString(data, "projectId"));
        return McR.success();
    }

    /// todo workspace/sync //手动触发, 知识库权限矩阵同步

    /**
     * 知识库版本管理
     */
    @PostMapping("approve/version")
    McR approveVersion(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("知识库版本管理, {}", data);
        McException.assertParamException_Null(data, "taskId", "pCode");

        awClint.approveVersion(UtilMap.getString(data, "taskId"), UtilMap.getString(data, "pCode"));
        return McR.success();
    }

    /**
     * 获取主数据产品列表
     */
    @GetMapping("product/list")
    Map getProductList(@RequestParam Map param) {
        String projectId = UtilMap.getString(param, "projectId");
        String q = UtilMap.getString(param, "q");
        List result = awClint.getProductList(projectId, q);
        return UtilMap.map("options", result);
    }

    /**
     * 获取主数据产品版本
     */
    @GetMapping("product/version")
    Map getProductVersionList(@RequestParam Map param) {
        String projectId = UtilMap.getString(param, "projectId");
        String q = UtilMap.getString(param, "q");
        String objectId = UtilMap.getString(param, "objectId");
        List result = awClint.getProductList(projectId, q, objectId);
        return UtilMap.map("options", result);
    }

    /**
     * 检查项导出, 全部检查项左关联已提交数据
     */
    @PostMapping("check-list/export")
    void exportCheckList(@RequestBody Map data, HttpServletResponse response) {

        log.info("检查项导出, {}", data);
        McException.assertParamException_Null(data, "pCode", "proType");

        List<Map> dataList = awClint.exportCheckList(UtilMap.getString(data, "pCode"), UtilMap.getString(data, "proType"));
        UtilExcel.exportMapAndListByTemplate(response, dataList, Map.class, UtilMap.getString(data, "pCode") + " 技术检查项目", "templates_checked_list.xlsx");
    }

    /************************************* 宜搭结构化 *************************************/


    @Autowired
    private AWYDClient awydClient;

    /// 产品型号、产品版本、客户、专项需求 todo 非文本导出异常兼容, Can not find 'Converter' support class ArrayList.
    private void _multiSelectCompatibility(List<Map> dataList) {
        List<String> compIds = Arrays.asList("multiSelectField_lw678e43", "multiSelectField_m11u62on", "multiSelectField_m0afm8pc", "multiSelectField_lticsrqp");
        for (Map map : dataList) {
            for (String compId : compIds) {
                if (compId.startsWith("multiSelectField_")) {
                    map.put(compId, String.join(",", UtilMap.getList(map, compId)));
                    continue;
                }
            }
        }
    }

    /**
     * 项目需求子表导出
     */
    @PostMapping("pro-req/export")
    void exportProjectRequirements(@RequestBody Map data, HttpServletResponse response) {

        log.info("项目需求子表导出, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "dataList", "fileName");

        List<Map> dataList = UtilMap.getList(data, "dataList");
        this._multiSelectCompatibility(dataList);
        String fileName = UtilMap.getString(data, "fileName"); // 需求维护
        UtilExcel.exportMapAndListByTemplate(response, dataList, Map.class, fileName, "templates_project_requirements.xlsx");
    }

    /**
     * 项目需求子表导入
     */
    @PostMapping("pro-req/import")
    McR importProjectRequirements(@RequestBody Map data, HttpServletResponse response) {

        log.info("项目需求子表导入, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "charter", "dataList", "fileName");
        Map result = awydClient.checkImportData_projectRequirements(UtilMap.getString(data, "charter"), UtilMap.getList(data, "dataList"), UtilMap.getBoolean(data, "isSubmit"));
        List<Map> dataList = UtilMap.getList(result, "dataList");
        if (UtilMap.getBoolean(result, "isSuccess")) {
            return McR.success(dataList);
        }
        this._multiSelectCompatibility(dataList);
        String fileName = UtilMap.getString(data, "fileName"); // 需求维护
        UtilExcel.exportMapAndListByTemplate(response, dataList, Map.class, fileName, "templates_project_requirements_exception.xlsx");
        return McR.errorAccess("数据校验失败");
    }

    /**
     * 项目需求审批通过
     */
    @PostMapping("pro-req/approve")
    McR approveProjectRequirements(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("项目需求审批通过, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "pCode", "instanceId", "userId");
        awydClient.dealApprovedData_projectRequirements(UtilMap.getString(data, "pCode"), UtilMap.getString(data, "instanceId"), data);
        return McR.success();
    }

    /**
     * 覆盖项目需求档案需求列表 tmp
     */
    @Deprecated
    @PostMapping("pro-req/archive")
    McR archiveProjectRequirements(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("覆盖项目需求档案需求列表, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "pCode", "instanceId");
        awydClient.archiveProjectRequirements(UtilMap.getString(data, "pCode"), UtilMap.getString(data, "instanceId"));
        return McR.success();
    }

    /**
     * 项目规格子表导出
     */
    @PostMapping("pro-spec/export")
    void exportProjectSpecification(@RequestBody Map data, HttpServletResponse response) {

        log.info("项目规格子表导出, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "dataList", "fileName");

        List<Map> dataList = UtilMap.getList(data, "dataList");
        this._multiSelectCompatibility(dataList);
        String fileName = UtilMap.getString(data, "fileName"); // 规格维护
        UtilExcel.exportMapAndListByTemplate(response, dataList, Map.class, fileName, "templates_project_specification.xlsx");
    }

    /**
     * 项目规格子表导入
     */
    @PostMapping("pro-spec/import")
    McR importProjectSpecification(@RequestBody Map data, HttpServletResponse response) {

        log.info("项目规格子表导入, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "charter", "dataList", "fileName", "prList");
        Map result = awydClient.checkImportData_projectSpecification(UtilMap.getString(data, "charter"), UtilMap.getList(data, "dataList"), UtilMap.getList(data, "prList"), UtilMap.getBoolean(data, "isSubmit"));
        List<Map> dataList = UtilMap.getList(result, "dataList");
        if (UtilMap.getBoolean(result, "isSuccess")) {
            return McR.success(dataList);
        }
        this._multiSelectCompatibility(dataList);
        String fileName = UtilMap.getString(data, "fileName"); // 需求维护
        UtilExcel.exportMapAndListByTemplate(response, dataList, Map.class, fileName, "templates_project_specification_exception.xlsx");
        return McR.errorAccess("数据校验失败");
    }

    /**
     * 项目规格审批通过
     */
    @PostMapping("pro-spec/approve")
    McR approveProjectSpecification(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("项规格审批通过, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "instanceId");
        awydClient.dealApprovedData_projectSpecification(UtilMap.getString(data, "instanceId"), data);
        return McR.success();
    }

    /**
     * 测试规格子表导出
     */
    @PostMapping("test-spec/export")
    void exportTestSpecification(@RequestBody Map data, HttpServletResponse response) {

        log.info("测试规格子表导出, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "dataList", "fileName");

        List<Map> dataList = UtilMap.getList(data, "dataList");
        this._multiSelectCompatibility(dataList);
        String fileName = UtilMap.getString(data, "fileName"); // 测试规格维护
        UtilExcel.exportMapAndListByTemplate(response, dataList, Map.class, fileName, "templates_test_specification.xlsx");
    }

    /**
     * 测试规格子表导入
     */
    @PostMapping("test-spec/import")
    McR importTESTSpecification(@RequestBody Map data, HttpServletResponse response) {

        log.info("测试规格子表导入, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "charter", "dataList", "fileName", "prList");
        Map result = awydClient.checkImportData_testSpecification(UtilMap.getString(data, "charter"), UtilMap.getList(data, "dataList"), UtilMap.getList(data, "prList"), UtilMap.getBoolean(data, "isSubmit"));
        List<Map> dataList = UtilMap.getList(result, "dataList");
        if (UtilMap.getBoolean(result, "isSuccess")) {
            return McR.success(dataList);
        }
        this._multiSelectCompatibility(dataList);
        String fileName = UtilMap.getString(data, "fileName"); // 需求维护
        UtilExcel.exportMapAndListByTemplate(response, dataList, Map.class, fileName, "templates_test_specification_exception.xlsx");
        return McR.errorAccess("数据校验失败");
    }

    /**
     * 测试规格审批通过
     */
    @PostMapping("test-spec/approve")
    McR approveTestSpecification(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("测试格审批通过, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "instanceId");
        awydClient.dealApprovedData_testSpecification(UtilMap.getString(data, "instanceId"), data);
        return McR.success();
    }

    /**
     * 测规格需求书子表导出
     */
    @PostMapping("test-req/export")
    void exportTestRequirements(@RequestBody Map data, HttpServletResponse response) {

        log.info("项目需求子表导出, {}", JSON.toJSONString(data));
        McException.assertParamException_Null(data, "dataList", "fileName");

        List<Map> dataList = UtilMap.getList(data, "dataList");
        this._multiSelectCompatibility(dataList);
        String fileName = UtilMap.getString(data, "fileName"); // 需求维护
        UtilExcel.exportMapAndListByTemplate(response, dataList, Map.class, fileName, "templates_project_requirements_test.xlsx");
    }

    /**
     * 提供verifier数据读取服务
     */
    @GetMapping("verifier/sync")
    McR syncVerifier(@RequestParam String projectCode, String productCode, String productVersion) {

        Map result = awydClient.syncVerifier(projectCode, productCode, productVersion);
        log.info("syncVerifier, {}, {}, {}", projectCode, productCode, productVersion);
        return McR.success(result);
    }

    /**
     * 提供verifier数据回写服务
     */
    @PostMapping("verifier/back")
    McR backVerifier(@RequestBody Map data) {

        log.info("backVerifier, {}", data);
        McException.assertParamException_Null(data, "code", "data");

        awydClient.backVerifier(data);
        return McR.success();
    }

    /**
     * 导出 [0909 作废版本1.0]
     */
    @PostMapping("export")
    void export(@RequestBody Map data, HttpServletResponse response) {
        List<Map> dataList = UtilMap.getList(data, "dataList");
        String fileName = UtilMap.getString(data, "fileName");
        String tempFileName = UtilMap.getString(data, "tempFileName");
        UtilExcel.exportMapAndListByTemplate(response, dataList, Map.class, fileName, tempFileName);
    }

    /**
     * 导入前处理 [0909 作废版本1.0]
     */
    @PostMapping("beforeImportData")
    McR beforeImportData(@RequestBody Map data, HttpServletResponse response) {
        Map result = awydClient.checkImportData(data);
        Boolean flag = UtilMap.getBoolean(result, "flag");
        List<Map> resultData = UtilMap.getList(result, "data");
        if (flag) {
            return McR.success(resultData);
        } else {
            String fileName = "异常";
            String tempFileName = "templates_xqwh_result.xlsx";
            UtilExcel.exportMapAndListByTemplate(response, resultData, Map.class, fileName, tempFileName);
            return null;
        }
    }

    //////// test ////////

    @Autowired
    private TBClient tbClient;

    @Autowired
    private TBConf tbConf;

    @Autowired
    private DDConf ddConf;


    @GetMapping("t/task")
    McR task(String taskId) {

        log.info("taskId, {}", taskId);
        List<Map> tList = tbClient.queryTaskDetail(taskId, "", "");
        return McR.success(tList);
    }

    @GetMapping("t/template")
    McR template(String name) {

        List<Map> tList = tbClient.templateSearch(null, name);
        return McR.success(tList);
    }

    @Autowired
    private YDClient ydClient;

    @Autowired
    private YDService ydService;

    @Autowired
    private McDelegate mcDelegate;

    @GetMapping("test")
    McR test(HttpServletRequest request) {

        Map<String, ?> data = UtilServlet.getParamMap(request);
        log.info("test, {}", data);


//        awClint.taskLevelValidate(UtilMap.map("projectId, taskId", "659376ba950780b816c33d3b, 66116073ea68df0235b30bef"));

//        try {
//            Map body = TBConf.assembleCustomFieldName(AWServer.TASK_TRANSMIT, "已下达");
//            tbClient.updateTaskCustomField("659a681d44ade3345fdc0d39", tbConf.getOperatorId(), body);
//        } catch (McException e) {
//            log.error(e.getMessage(), e);
//        }

        awClint.test();
//        awydClient.test();

//        ydClient.operateData(YDParam.builder()
//                .formInstanceId("9d204da7-b01e-4bd9-a673-acb9b64b0e61")
//                .updateFormDataJson(JSON.toJSONString(UtilMap.map("radioField_lu9yf7vg", "否")))
//                .useLatestVersion(true)
//                .build(), YDConf.FORM_OPERATION.update);
        return McR.success();
    }

    @GetMapping("tmp")
    McR tmp(String programIds) {

//        awClint.tmp();

//        List<String> tags = tbClient.queryProjectTag("66c763a2a86f837e07c418e9", tbConf.getOperatorId());
//        tags.add("111");


        return McR.success();
    }
}
