package com.malk.tuosi.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.malk.server.common.McException;
import com.malk.server.common.McR;
import com.malk.server.common.VenR;
import com.malk.server.dingtalk.DDConf;
import com.malk.server.dingtalk.DDR_New;
import com.malk.service.dingtalk.DDClient;
import com.malk.service.dingtalk.DDClient_Extension;
import com.malk.tuosi.service.TBService;
import com.malk.utils.UtilHttp;
import com.malk.utils.UtilMap;
import com.sun.crypto.provider.PBEWithMD5AndDESCipher;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.net.URL;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TbServiceImpl implements TBService {


    /*TODO:TB获取应用token*/
    @Override
    public McR AppAccessToken() throws JsonProcessingException {
        HashMap body = new HashMap();
        body.put("appId","6874ba11d22c73565fd8af9d");
        body.put("appSecret","4JBgPwpctG27SuZrVVeCrXoiVCjie9ID");
        String doPost = UtilHttp.doPost("https://open.teambition.com/api/appToken",null,null,body);
        // 使用 Fastjson 解析 JSON
        JSONObject jsonObject = JSONObject.parseObject(doPost);
        String appToken = jsonObject.getString("appToken");
        log.info("Toke：{}",appToken);
        return McR.success(appToken);
    }

    /*TODO：钉钉获取应用token（欧诺架构）*/
    public McR Accesstoken() throws JsonProcessingException{
        HashMap params = new HashMap();
        params.put("appkey","dingtjgevp4t9vnlmpbj");
        params.put("appsecret","Q3CzrNIj4HjON8buv4zClgpf-A0cW5uDRB5UtMHJHAHuQDj-g1nmq-h7EeYe_i5a");
        String doGet = UtilHttp.doGet("https://oapi.dingtalk.com/gettoken", null, params);
        JSONObject jsonObject = JSONObject.parseObject(doGet);
        String accessToken = jsonObject.getString("access_token");
        log.info("accessToken：{}",accessToken);
        return McR.success(accessToken);
    }

    /*TODO:钉钉获取应用token（欧诺信架构）*/
    @Override
    public McR OuNuoXinAccessToken() throws JsonProcessingException {
        HashMap params = new HashMap();
        params.put("appkey","dingi61ncsi1zjo7eosp");
        params.put("appsecret","unvpxWgDeYEokuUlD-4iyDh0NdRH3NRKE1OkDF8VPQwyYi0Nuo_uXTWBYxnKYJaI");
        String doGet = UtilHttp.doGet("https://oapi.dingtalk.com/gettoken", null, params);
        JSONObject jsonObject = JSONObject.parseObject(doGet);
        String accessToken = jsonObject.getString("access_token");
        log.info("accessToken：{}",accessToken);
        return McR.success(accessToken);
    }

    /*TODO：接收TB推送的数据*/
    @SneakyThrows
    @Override
    public McR tbTaskUpdate(Map body) throws JsonProcessingException {
        String s = JSON.toJSONString(body);
        JSONObject jsonObject = JSON.parseObject(s);
        String event = jsonObject.getString("event");
        //一层过滤：过滤事件[任务自定义字段更新事件]
        if (event.equals("v3.task.customfield.update")){
            JSONObject data = jsonObject.getJSONObject("data");
            System.out.println(data);
            //二层过滤：过滤任务字段[只允许work类型字段类型生效]】
            String customfieldId = data.getString("customfieldId");//自定义字段ID
            // 1、版线组附件：6889f02fc74205217edfa65b 2、3D效果图：689d9834591915184b095e5f  3、白盒视频：6889c49443cbd3a23c9dc55f
            //todo:版线组附件回传CRM
            if(customfieldId.equals("6889f02fc74205217edfa65b") && data.getString("customfieldOldValue").equals("[]")){
                log.info("第一次上传，版线组附件为空");
                tbCallbackCRM(data);
            }
            String customfieldType = data.getString("customfieldType");//自定义字段类型
            String taskId = data.getString("taskId");//任务id
            if(customfieldType.equals("work")){
                /*TODO:查询任务详情，字段值，获取metaString*/
                HashMap head = new HashMap();
                McR accessToken = AppAccessToken();
                Object tokenData = accessToken.getData();
                head.put("Authorization","Bearer " + tokenData);
                head.put("X-Tenant-Id","61a8c26719c3b5ffe9c4cffb");
                head.put("X-Tenant-Type","organization");

                HashMap param = new HashMap();
                param.put("taskId",taskId);
                String doGet = UtilHttp.doGet("https://open.teambition.com/api/v3/task/query", head, param);//查询任务详情
                ObjectMapper objectMapper = new ObjectMapper();
                JsonNode rootNode = objectMapper.readTree(doGet);
                for(JsonNode resultNode : rootNode.path("result")){
                    String content = resultNode.path("content").asText();//任务名称
                    String customerName = "";//客户简称
                    String manager = "";//节点负责人
                    String designTime = "";//设计完成时间
                    for(JsonNode customField : resultNode.path("customfields")) {
                        String cfId = customField.path("cfId").asText();
                        if ("68c23d6fee5aa63b8da58878".equals(cfId)) {
                            JsonNode valueArray = customField.path("value");
                            if (valueArray.isArray() && valueArray.size() > 0) {
                                String dateTimeStr = valueArray.get(0).path("title").asText();
                                // 解析UTC时间
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                                sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
                                Date date = sdf.parse(dateTimeStr);
                                // 直接格式化为本地时间（不需要加8小时）
                                SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                                designTime = outputFormat.format(date);
                            }
                        }
                    }
                    for(JsonNode customField : resultNode.path("customfields")){
                        String cfId = customField.path("cfId").asText();
                        if ("687df3b60ae1530fa2704499".equals(cfId)) {
                            // 获取 value 数组中的第一个元素的 title
                            JsonNode valueArray = customField.path("value");
                            if (valueArray.isArray() && valueArray.size() > 0) {
                                customerName = valueArray.get(0).path("title").asText();//客户简称
                            }
                        }else if ("66bb1a56f7e230ed6843796e".equals(cfId)){
                            JsonNode valueArray = customField.path("value");
                            if (valueArray.isArray() && valueArray.size() > 0) {
                                manager = valueArray.get(0).path("title").asText();//节点负责人
                            }
                        } else if ("68c23d6fee5aa63b8da58878".equals(cfId)) {
                            JsonNode valueArray = customField.path("value");
                            if (valueArray.isArray() && valueArray.size() > 0) {
                                String dateTimeStr = valueArray.get(0).path("title").asText();
                                // 解析UTC时间
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                                sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
                                Date date = sdf.parse(dateTimeStr);
                                // 加上8小时（转换为北京时间）
                                Calendar calendar = Calendar.getInstance();
                                calendar.setTime(date);
                                calendar.add(Calendar.HOUR_OF_DAY, 8);
                                // 格式化为 "yyyy-MM-dd HH:mm"
                                SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                                designTime = outputFormat.format(calendar.getTime());//设计完成时间
                            }
                        }
                        if(customfieldId.equals(cfId)){
                            String writeValueAsString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(customField);
                            //解析metaString中的resourceId(附件可能会上传多个，所以得遍历customfield里面的值)
                            ObjectMapper mapper = new ObjectMapper();
                            JsonNode node = mapper.readTree(writeValueAsString);
                            JsonNode valueArray =  node.path("value");
                            //检查value数组是否存在&不为空
                            if(valueArray.isArray() && valueArray.size() > 0){
                                List<String> allResourceIds = new ArrayList<>();
                                List<String> allFileNames = new ArrayList<>();
                                //遍历所有的value节点，收集resourceId和文件名title
                                String resourceId = "";
                                for (int i=0;i<valueArray.size();i++){
                                    JsonNode valueNode = valueArray.get(i);
                                    String metaString = valueNode.path("metaString").asText();
                                    String title = valueNode.path("title").asText();

                                    JsonNode metaJson = objectMapper.readTree(metaString);
                                    resourceId = metaJson.path("resourceId").asText();
                                    allResourceIds.add(resourceId);
                                    allFileNames.add(title);
                                }
                                if(!allResourceIds.isEmpty()){
                                    //根据resourceId获取文件详情 POST https://open.teambition.com/api/v3/file/query/by-resource-ids
                                    HashMap haader = new HashMap();
                                    haader.put("Content-Type", "application/json");
                                    haader.put("Authorization", "Bearer " + tokenData);
                                    haader.put("x-operator-id", "622ee3450cf3bb5e1a486f1f");
                                    haader.put("X-Tenant-Id", "61a8c26719c3b5ffe9c4cffb");
                                    haader.put("X-Tenant-Type", "organization");

                                    HashMap boody = new HashMap();
                                    boody.put("resourceIds",allResourceIds);
                                    boody.put("needSign",true);

                                    String fileDownloadResponse = UtilHttp.doPost("https://open.teambition.com/api/v3/file/query/by-resource-ids", haader, null, boody);

                                    JSONObject response = JSON.parseObject(fileDownloadResponse);
                                    JSONArray resultArray = response.getJSONArray("result");

                                    if(resultArray != null && resultArray.size() > 0){
                                        //todo:3D效果图放在新图案  白盒视频放在白盒库
                                        String basedir = "";
                                        String fileType = "";//附件类型：新图案(199256463063)、白盒(199256765924)
                                        if(customfieldId.equals("689d9834591915184b095e5f")){
                                            basedir = "C:/downloads/附件存储/新图案";
                                            fileType = "199256463063";
                                        }else if(customfieldId.equals("6889c49443cbd3a23c9dc55f")){
                                            basedir = "C:/downloads/附件存储/白盒库";
                                            fileType = "199256765924";
                                        }else {
                                            basedir = "C:/downloads/附件存储/其它";
                                        }
                                        List<String> successDownloads = new ArrayList<>();
                                        List<String> failedDownloads = new ArrayList<>();
                                        //遍历所有结果，下载每个文件（只需要拿到最新的内容即可）
                                        for (int i=0;i< resultArray.size();i++) {
                                            JSONObject fileObject = resultArray.getJSONObject(i);
                                            String downloadUrl = fileObject.getString("downloadUrl");
                                            //文件名称：设计完成时间-任务名称-客户简称-节点负责人-附件名称
                                            String fileName = designTime + "_" + content + "_" + customerName + "_" + manager + "_" + fileObject.getString("fileName");
                                                try {
                                                    String savePath = downloadFile(downloadUrl, basedir, fileName);
                                                    successDownloads.add(fileName + "->" + savePath);
                                                    System.out.println("[文件本地存储成功][" + i + "]=====>" + fileName + "保存路径：" + savePath);
                                                    /*TODO：钉盘文件存储一份*/
                                                    System.out.println("[开始上传文件到钉盘]");
                                                    uploadKnowledge(savePath, fileName,fileType);
                                                } catch (IOException e) {
                                                    failedDownloads.add(fileName + "->" + e.getMessage());
                                                    System.out.println("[文件下载失败][" + i + "]=====>" + fileName + "错误信息：" + e.getMessage());
                                                }
                                        }

                                    }else {
                                        System.out.println("[警告]未找到任何文件下载信息");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } else if (event.equals("v3.task.create")) {
            JSONObject data = jsonObject.getJSONObject("data");
            String sfcId = data.getString("sfcId");
            if (sfcId.equals("6878b3c0669d175c3c6bc679") || sfcId.equals("6878b3ceb5ffcf500365d17a") || sfcId.equals("6878b3d8f40485da4c5f99a2")
                || sfcId.equals("6878b39a27ae5f3cac355fb9") || sfcId.equals("6878b3a4090e6872fd6b78c6") || sfcId.equals("6878b3ad9e17ac8a027c6d37")
                || sfcId.equals("68999dc2d1cb63e672e0b503") || sfcId.equals("68999dcf3071884859cacb87") || sfcId.equals("6878b3b60d49d89e7955726f")
                || sfcId.equals("68999dd990de390188d8bee6")){
                String taskId = data.getString("taskId");
                HashMap header = new HashMap();
                header.put("x-operator-id","622ee3450cf3bb5e1a486f1f");//xmy
                McR Token = AppAccessToken();
                Object token = Token.getData();
                header.put("Authorization","Bearer " + token);
                header.put("X-Tenant-type","organization");
                header.put("X-Tenant-Id","61a8c26719c3b5ffe9c4cffb");
                HashMap body_AAA = new HashMap();
                String nodeId = null;
                switch (sfcId){
                    case "6878b3c0669d175c3c6bc679" :
                        nodeId = "6875ba31ff8968791e009dad";
                        break;
                    case "6878b3ceb5ffcf500365d17a" :
                        nodeId = "6875c12442b4476582041a90";
                        break;
                    case "6878b3d8f40485da4c5f99a2" :
                        nodeId = "6875c736476bc6384b458cfa";
                        break;
                    case "6878b39a27ae5f3cac355fb9" :
                        nodeId = "6875f3cf4b7eb5199098892c";
                        break;
                    case "6878b3a4090e6872fd6b78c6" :
                        nodeId = "6875f5e40a12fb0d64feb1e2";
                        break;
                    case "6878b3ad9e17ac8a027c6d37" :
                        nodeId = "6875f78e43d815a435aa9308";
                        break;
                    case "68999dc2d1cb63e672e0b503" :
                        nodeId = "6880881feac3a8e8f6e3aead";
                        break;
                    case "68999dcf3071884859cacb87" :
                        nodeId = "68808b96767bd365b1b7b6f5";
                        break;
                    case "6878b3b60d49d89e7955726f" :
                        nodeId = "6874c857ad8265662925a6ae";
                        break;
                    case "68999dd990de390188d8bee6":
                        nodeId = "6880912c9c778244636507f8";
                        break;
                }
                body_AAA.put("nodeId",nodeId);
                String doPut = UtilHttp.doPut(
                        "https://open.teambition.com/api/v3/task/" + taskId + "/node/complete",
                        header,
                        null,
                        body_AAA);
                log.info("自动流程确认，任务id: {}",taskId );
                log.info("[创建任务自动更新确认流程],{}",doPut);
            }
        }else if (event.equals("v3.task.node.status.update")) {
            /*群卡片推送*/
            JSONObject data = jsonObject.getJSONObject("data");
            String nodeId = data.get("nodeId").toString();
            String taskId = data.get("taskId").toString();
            if(("6875f58cf512415e5944c64c".equals(nodeId) || "6878a073eaa6f6ff736a5575".equals(nodeId)) && data.get("status").equals("finish")){//主管确认（1）  6875f58cf512415e5944c64c   主管确认（2）6878a073eaa6f6ff736a5575
                /*设计单主管确认节点*/
                List<String> allResourceIds = new ArrayList<>();//存储文件的ids
                List<String>  downloadUrls= new ArrayList<>();//存储文件下载地址(原来的)
                List<String> newdownloadUrls = new ArrayList<>();//卡片存储文件地址(新的)
                /*所有的字段信息定义*/
                String content = "";//todo:任务名称
                List<String> involveMembers = new ArrayList<>();//todo:负责人
                String businessManager = "";//todo:业务经理
                String businessPerson = "";//todo:业务人员
                String customerName = "";//todo:客户名称
                String downloadUrl = "";
                String valueAsString = "";//todo:文件下载地址（jsonString）

                HashMap head = new HashMap();
                McR accessToken = AppAccessToken();
                Object tokenData = accessToken.getData();
                head.put("Authorization","Bearer " + tokenData);
                head.put("X-Tenant-Id","61a8c26719c3b5ffe9c4cffb");
                head.put("X-Tenant-Type","organization");
                HashMap param = new HashMap();
                param.put("taskId",taskId);
                String doGet = UtilHttp.doGet("https://open.teambition.com/api/v3/task/query", head, param);//查询任务详情
                ObjectMapper objectMapper = new ObjectMapper();
                JsonNode rootNode = objectMapper.readTree(doGet);
                JsonNode result = rootNode.path("result");
                for(JsonNode resultNode : rootNode.path("result")){
                    content = resultNode.path("content").asText();//todo:任务名称

                    JsonNode customFields = resultNode.path("customfields");
                    if (customFields.isArray()) {
                        for (JsonNode field : customFields) {
                            String cfId = field.path("cfId").asText();
                            // 检查是否有 value 数组
                            JsonNode valueArray = field.path("value");
                            if (!valueArray.isArray() || valueArray.size() == 0) {
                                continue;
                            }
                            // 获取第一个 value 对象
                            JsonNode firstValue = valueArray.get(0);
                            switch (cfId) {
                                case "687df458b9c2f9f90865c13b": // todo：业务经理
                                    businessManager = firstValue.path("title").asText();
                                    System.out.println("业务经理: " + businessManager);
                                    break;

                                case "688191972ab6c4f412ea2bb9": // todo：业务人员
                                    businessPerson = firstValue.path("title").asText();
                                    System.out.println("业务人员: " + businessPerson);
                                    break;

                                case "687df3b60ae1530fa2704499": // todo：客户名称
                                    customerName = firstValue.path("title").asText();
                                    System.out.println("客户名称: " + customerName);
                                    break;

                                case "689d9834591915184b095e5f": // todo：附件 metaString
                                    JsonNode valueArray1 = field.path("value");
                                    if (valueArray1.isArray()) {
                                        for (JsonNode attachment : valueArray) {
                                            String metaString = attachment.path("metaString").asText();
                                            String title = attachment.path("title").asText();
                                            String director = title.substring(title.lastIndexOf("-") + 1, title.lastIndexOf("."));
                                            involveMembers.add(director);
                                            if (!metaString.isEmpty()) {
                                                ObjectMapper mapper = new ObjectMapper();
                                                JsonNode metaJson = mapper.readTree(metaString);
                                                String resourceId = metaJson.path("resourceId").asText();
                                                allResourceIds.add(resourceId);
                                            }
                                        }
                                    }
                                    HashMap haader = new HashMap();
                                    haader.put("Content-Type", "application/json");
                                    haader.put("Authorization", "Bearer " + tokenData);
                                    haader.put("x-operator-id", "622ee3450cf3bb5e1a486f1f");
                                    haader.put("X-Tenant-Id", "61a8c26719c3b5ffe9c4cffb");
                                    haader.put("X-Tenant-Type", "organization");

                                    HashMap boody = new HashMap();
                                    boody.put("resourceIds",allResourceIds);
                                    boody.put("needSign",true);

                                    String fileDownloadResponse = UtilHttp.doPost("https://open.teambition.com/api/v3/file/query/by-resource-ids", haader, null, boody);
                                    JSONObject response = JSON.parseObject(fileDownloadResponse);
                                    JSONArray resultArray = response.getJSONArray("result");
                                    for (int i=0;i< resultArray.size();i++) {
                                        JSONObject fileObject = resultArray.getJSONObject(i);
                                        downloadUrl = fileObject.getString("downloadUrl");
                                        downloadUrls.add(downloadUrl);
                                    }
                                    System.out.println("下载地址" + downloadUrls);//原下载地址

                                    //todo:把照片存在file目录下

                                    if(resultArray != null && resultArray.size()>0){
                                        String basedir = "file";
                                        ArrayList successDownloads = new ArrayList();
                                        ArrayList faileDownloads = new ArrayList();
                                        for (int i=0;i<resultArray.size();i++){
                                            JSONObject fileObject = resultArray.getJSONObject(i);//新下载地址
                                            String downloadUrl1 = fileObject.getString("downloadUrl");
                                            long millisTimestamp = System.currentTimeMillis();//当前时间戳
//                                            String fileName = millisTimestamp + "_" + fileObject.getString("fileName");//去掉了时间戳
                                            String fileName = fileObject.getString("fileName");
                                            try{
                                                String savePath = downloadFile(downloadUrl1,basedir,fileName);//TODO；存储图片至file目录下
                                                successDownloads.add(fileName + "->" + savePath);
                                                System.out.println("文件存储成功["+i+"]=====>"+fileName+"保存路径："+savePath);
//                                                String newsavepath = "http://ounuo.raresoft.net:7880/file/"+fileName;
                                                String newsavepath = "http://192.168.22.152:7880/file/"+fileName;//换成欧诺公司内部的访问地址
                                                newdownloadUrls.add(newsavepath);
                                            }catch (IOException e){
                                                faileDownloads.add(fileName+"->"+e.getMessage());
                                                System.out.println("文件下载失败["+i+"]=====>"+fileName+"错误信息："+e.getMessage());
                                            }
                                        }
                                    }

                                    ObjectMapper mapper = new ObjectMapper();
                                    // 使用Stream API创建List<Map<String, String>>
                                    List<Map<String, String>> res = newdownloadUrls.stream()
                                            .map(url -> {
                                                Map<String, String> map = new LinkedHashMap<>(); // 保持顺序
                                                map.put("arr", url);
                                                return map;
                                            })
                                            .collect(Collectors.toList());
                                    valueAsString = mapper.writeValueAsString(res);
                                    System.out.println("格式化后的下载地址：" + valueAsString);
                                    break;
                            }
                        }
                    }
                    System.out.println(); // 空行分隔
                }
                //组装数据卡片推送
                // 业务经理=宁学刚推送至“郝总—节令—设计对接”cid2niI2sTPksK5PHpfrLgCPQ==   业务经理=姜华推送至“姜华—流通—设计对接”cid+J9H07847VNwIYiLpNay0Q==  业务经理=谷晨丹推送至“谷晨丹—烘焙—设计对接”cidqXtqGAN+Es7L/5m3uaZzSg==  业务经理=赵宇娟推送至"赵宇娟—烘焙—设计对接"cidaUtMTIjDHM60UXFfHegKtg==
                JSONObject cardData = new JSONObject();
                cardData.put("name_task", content);
                cardData.put("designer", String.join("，", involveMembers));
                cardData.put("name_person", businessManager + "，" + businessPerson);
                cardData.put("name_customer", customerName);
                cardData.put("arr_picture", valueAsString);//todo：里面的每个需要转成jsonString类型
                cardData.put("link","https://www.teambition.com/project/6878b323386fac7ab9dbe5e9/tasks/view/6878b323cc336006f34d1d22/task/"+taskId);
                cardData.put("picture_link",generateHtmlLinks(valueAsString));

                JSONObject message = new JSONObject();
                message.put("cardData", cardData);
                message.put("outTrackId", String.valueOf(System.currentTimeMillis()));
                if("宁学刚".equals(businessManager)){
                    message.put("openSpaceId", "dtv1.card//IM_GROUP.cid2niI2sTPksK5PHpfrLgCPQ==");
                } else if ("姜华".equals(businessManager)) {
                    message.put("openSpaceId", "dtv1.card//IM_GROUP.cid+J9H07847VNwIYiLpNay0Q==");
                }else if ("赵宇娟".equals(businessManager) || "孟露".equals(businessManager)) {
                    message.put("openSpaceId", "dtv1.card//IM_GROUP.cidaUtMTIjDHM60UXFfHegKtg==");
                } else if ("陈晶".equals(businessManager) || "郝俊秀".equals(businessManager)) {
                    message.put("openSpaceId", "dtv1.card//IM_GROUP.cidTppONwRCrkshRlCt28O+NA==");
                }else if ("张曼".equals(businessManager)){
                    message.put("openSpaceId","dtv1.card//IM_GROUP.cidXES2AIusSs+mb9gD8i4w1w==");
                }else if("张昆".equals(businessManager)){
                    message.put("openSpaceId","dtv1.card//IM_GROUP.cidI3G/EnCvlem5w3+qKfTMDA==");
                }else if("谷晨丹".equals(businessManager)){
                    message.put("openSpaceId","dtv1.card//IM_GROUP.cidqXtqGAN+Es7L/5m3uaZzSg==");
                }else if("鲁萍".equals(businessManager)){
                    message.put("openSpaceId","dtv1.card//IM_GROUP.cidibXgbOJLBc5L8xHNRzo5Jg==");
                }
//                message.put("openSpaceId", "dtv1.card//IM_GROUP.cidKoVDKhvynnj+73h0uxSJBA==");//正式群id：cidTppONwRCrkshRlCt28O+NA==   测试群id:cidKoVDKhvynnj+73h0uxSJBA==
                message.put("cardTemplateId", "7c91d56c-5dee-4294-88a5-f68238854030.schema");//160b26bf-d699-49fc-a6dc-9cd20eed7750.schema
                message.put("robotCode", "dinghhozexm92tupobfo");
//                message.put("link","https://www.teambition.com/project/6878b323386fac7ab9dbe5e9/tasks/view/6878b323cc336006f34d1d22/task/" + taskId);
                createAndDeliverCard(message);//调用卡片推送
            }
        }
         return McR.success();
    }

    /*TODO：钉盘文件上传*/
    @SneakyThrows
    @Override
    public McR uploadKnowledge(String pathName,String fileName,String fileType) throws JsonProcessingException {
        /*TODO：step1：获取上传文件需要的resourceUrls和headers参数值*/
        HashMap head = new HashMap();
        McR accessToken = Accesstoken();
        Object tokenData = accessToken.getData();
        head.put("x-acs-dingtalk-access-token",tokenData);

        HashMap params = new HashMap();
        params.put("unionId","Vwt6seFpRYYCh1yj2BBTCwiEiE");

        HashMap body = new HashMap();
        body.put("protocol","HEADER_SIGNATURE");//默认
        body.put("multipart",false);//5G以下文件，设为false
        DDR_New deptDDR  = (DDR_New) UtilHttp.doPost("https://api.dingtalk.com/v1.0/storage/spaces/27116552652/files/uploadInfos/query", head, params, body, DDR_New.class);
        Map headerSignatureInfo = deptDDR.getHeaderSignatureInfo();
        /*TODO：step2：使用OSS的header加签方式上传文件*/
        List<String> resourceUrls = (List<String>) headerSignatureInfo.get("resourceUrls");
        //从接口中获取到resourceUrl
        String resourceUrl = resourceUrls.get(0);
        //从接口中获取到headers
        Map<String, String> headers = (Map<String, String>) headerSignatureInfo.get("headers");
        URL url = new URL(resourceUrl);
        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                connection.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        connection.setDoOutput(true);
        connection.setRequestMethod("PUT");
        connection.setUseCaches(false);
        connection.setReadTimeout(10000);
        connection.setConnectTimeout(10000);
        connection.connect();
        OutputStream out = connection.getOutputStream();
        InputStream is = new FileInputStream(new File(pathName));
        byte[] b =new byte[1024];
        int temp;
        while ((temp=is.read(b))!=-1){
            out.write(b,0,temp);
        }
        out.flush();
        out.close();
        int responseCode = connection.getResponseCode();
        connection.disconnect();
        if (responseCode == 200) {
            System.out.println("上传成功");
        } else {
            System.out.println("上传失败");
        }
        /*TODO：step3：调用提交文件接口，完成文件上传*/
        HashMap param = new HashMap();
        param.put("unionId","Vwt6seFpRYYCh1yj2BBTCwiEiE");

        HashMap boddy = new HashMap();
        String uploadKey = deptDDR.getUploadKey();
        boddy.put("uploadKey",uploadKey);//添加文件唯一标识uploadKey
        boddy.put("name",fileName);//文件的名称,带后缀
        boddy.put("parentId",fileType);//父目录Id====> 白盒库：199256765924    新图案：199256463063

        HashMap header = new HashMap();
        header.put("x-acs-dingtalk-access-token",tokenData);
        String post = UtilHttp.doPost("https://api.dingtalk.com/v1.0/storage/spaces/27116552652/files/commit", header, param, boddy);
        return McR.success(post);
    }

    /*TODO：版线组位置附件上传CRM*/
    @Override
    public McR tbCallbackCRM(Map body) throws JsonProcessingException {
        String s = JSON.toJSONString(body);
        //解析参数拿到taskIda
        JSONObject object = JSON.parseObject(s);
        String taskId = object.getString("taskId");//任务id
        String customfieldId = object.getString("customfieldId");//自定义字段id
        //获取回传CRM中的crmid  metaString(若有)
        HashMap head = new HashMap();
        McR accessToken = AppAccessToken();
        Object tokenData = accessToken.getData();
        head.put("Authorization","Bearer " + tokenData);
        head.put("X-Tenant-Id","61a8c26719c3b5ffe9c4cffb");
        head.put("X-Tenant-Type","organization");
        HashMap param = new HashMap();
        param.put("taskId",taskId);
        String doGet = UtilHttp.doGet("https://open.teambition.com/api/v3/task/query", head, param);
        JSONObject responseJson = JSON.parseObject(doGet);
        JSONArray resultArray = responseJson.getJSONArray("result");
        String crmid = null;
        String metaString = null;
        String resourceId = null;
        List<String> resourceIds_AAA = new ArrayList<>();
        if(resultArray != null && !resultArray.isEmpty()){
            JSONObject task = resultArray.getJSONObject(0);
            JSONArray customFields = task.getJSONArray("customfields");
            if(customFields != null){
                for (int i = 0; i < customFields.size(); i++) {
                    JSONObject field = customFields.getJSONObject(i);
                    String cfId = field.getString("cfId");
                    if("689d4ebf343c05fe73700c93".equals(cfId)){//CRM单据ID
                        JSONArray valueArray = field.getJSONArray("value");
                        if(valueArray != null && !valueArray.isEmpty()){
                            JSONObject firstValue = valueArray.getJSONObject(0);
                            crmid = firstValue.getString("title");
                        }
                    }

                    if("6889f02fc74205217edfa65b".equals(cfId)){//版线位置附件
                        JSONArray array = field.getJSONArray("value");
                        if(array != null && !array.isEmpty()){
                            for (int j = 0; j < array.size(); j++) {
                                JSONObject firstValue1 = array.getJSONObject(j);
                                metaString =firstValue1.getString("metaString");
                                JSONObject jsonObject = JSON.parseObject(metaString);
                                resourceId  = jsonObject.getString("resourceId");
                            }
                            resourceIds_AAA.add(resourceId);
                        }
                    }

                }
            }
        }
        //获取当前变更时间 202x-0x-xx xx:xx:xx
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String jssj = now.format(formatter);
        //获取文件downloadurl（若有） 1、查询任务详情(拿到metaString)  2、获取文件下载URL
        String done = null;
        if(!metaString.isEmpty()){
            HashMap header = new HashMap();
            McR Token = AppAccessToken();
            Object token = Token.getData();
            header.put("Authorization","Bearer " + token);
            header.put("X-Tenant-Id","61a8c26719c3b5ffe9c4cffb");
            header.put("X-Tenant-Type","organization");
            HashMap bodyy = new HashMap();
            bodyy.put("needSign",true);
            bodyy.put("resourceIds",resourceIds_AAA);
            String post = UtilHttp.doPost("https://open.teambition.com/api/v3/file/query/by-resource-ids", header, null, bodyy);
            String downloadURL = JSON.parseObject(post).getJSONArray("result").getJSONObject(0).getString("downloadUrl");
            //获取文件名称
            String fileName = JSON.parseObject(post).getJSONArray("result").getJSONObject(0).getString("fileName");
            //TODO：调用TB回传CRM接口
            //构建请求头
            HashMap headers = new HashMap();
            headers.put("crmuserid","620131c2fe8d7eb6b8dfbf76");//tb的userid（固定是张昆）
            headers.put("TargetSystem","CRM");//固定值
            //构建params参数
            HashMap params = new HashMap();
            params.put("crmid",crmid);
            params.put("jssj",jssj);
            params.put("bxwz",downloadURL);
            params.put("bxwzsname",fileName);
            //构建body参数
            HashMap bodys = new HashMap();
            bodys.put("params",params);
            done = UtilHttp.doPost("http://ounuo.ip.raresoft.net:8888/api/dd/selfchange", headers, null, bodys);
        }

        return McR.success(done);
    }

    @Autowired
    private DDConf ddConf;
    @Autowired
    private DDClient ddClient;

    @Override
    public McR oaCallbackTB(Map body) throws JsonProcessingException {
        //获取单个审批实例详情
        HashMap params_AAA = new HashMap();
        params_AAA.put("appkey","dingi61ncsi1zjo7eosp");
        params_AAA.put("appsecret","unvpxWgDeYEokuUlD-4iyDh0NdRH3NRKE1OkDF8VPQwyYi0Nuo_uXTWBYxnKYJaI");
        String doGet = UtilHttp.doGet("https://oapi.dingtalk.com/gettoken", null, params_AAA);
        JSONObject jsonObject_AAA = JSONObject.parseObject(doGet);
        String accessToken = jsonObject_AAA.getString("access_token");

        HashMap head_AAA = new HashMap();
        head_AAA.put("x-acs-dingtalk-access-token",accessToken);
        HashMap params = new HashMap();
        String InstanceId = body.get("InstanceId").toString();
        params.put("processInstanceId",InstanceId);
        String s = UtilHttp.doGet("https://api.dingtalk.com/v1.0/workflow/processInstances", head_AAA, params);
        JSONObject jsonObject = JSON.parseObject(s);
        JSONObject jsonObject1 = jsonObject.getJSONObject("result");
        JSONArray jsonArray = jsonObject1.getJSONArray("operationRecords");
        String remark = "";
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject2 = jsonArray.getJSONObject(i);
            String type = jsonObject2.getString("type");
            String s1 = jsonObject2.getString("remark");
            if (type.equals("ADD_REMARK") && s1.contains("发起审批的 Teambition 任务")){
                remark = jsonObject2.getString("remark");
            }
        }
        //截取remark中()的内容
        String remarkStr111 = remark.substring(remark.indexOf("(") + 1, remark.indexOf(")"));
        String remarkStr222 = "";
        try {
            remarkStr222 = URLDecoder.decode(remarkStr111, "UTF-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        String remarkStr333 = "";
        try {
            remarkStr333 = URLDecoder.decode(remarkStr222, "UTF-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        //获取链接中的tasks/后?前的参数
        String strStart = "tasks/";
        String endStart = "?isDingtalkHeaderHidden";
        String taskId = remarkStr333.substring(remarkStr333.indexOf(strStart) + 6, remarkStr333.lastIndexOf(endStart));
        //更新任务
        double value = 0;
        String name = "";
        JSONArray array = jsonObject1.getJSONArray("formComponentValues");
        for (int j=0;j<array.size();j++){
            JSONObject object = array.getJSONObject(j);
            name = object.getString("name");
            if(name.equals("版费总价")){
                value = object.getDoubleValue("value");
            }
        }
        HashMap head = new HashMap();
        head.put("x-operator-id","622ee3450cf3bb5e1a486f1f");
        McR Token = AppAccessToken();
        Object tok = Token.getData();
        head.put("Authorization","Bearer " + tok);
        head.put("X-Tenant-type","organization");
        head.put("X-Tenant-Id","61a8c26719c3b5ffe9c4cffb");
        String finalName = name;
        double finalValue = value;
        HashMap<String,Object> bodyy =  new HashMap<String,Object>(){{
           put("customfieldName", finalName);
           put("value",Collections.singletonList(
                   new HashMap<String,String>() {{
                       put("title", String.valueOf(finalValue));
                   }}
           ));
        }};
        String s1 = UtilHttp.doPost("https://open.teambition.com/api/v3/task/" + taskId + "/customfield/update", head, null, bodyy);
        return McR.success(s1);
    }

    @Override
    public String TBtoDinguserId(List list) throws JsonProcessingException {
        System.out.println(list);
        HashMap header = new HashMap();
        McR accessToken = AppAccessToken();
        Object tokenData = accessToken.getData();
        header.put("Authorization","Bearer " + tokenData);
        header.put("X-Tenant-type","organization");
        header.put("X-Tenant-Id","61a8c26719c3b5ffe9c4cffb");
        HashMap param = new HashMap();
        param.put("tbUserIds",list);
        String s = UtilHttp.doGet("https://open.teambition.com/api/idmap/dingtalk/getDingUserId", header, param);
        ObjectMapper objectMapper = new ObjectMapper();
        var rootNode = objectMapper.readTree(s);
        List<String> userIdList  = objectMapper.convertValue(
                        rootNode.get("result"),
                        new TypeReference<List<Map<String, String>>>() {
                        }
                )
                .stream()
                .map(map -> map.get("dingtalkUserId"))
                .collect(Collectors.toList());
        //开始处理userid查询用户名称
        HashMap params = new HashMap();
        McR Token = OuNuoXinAccessToken();
        Object Data = Token.getData();
        params.put("access_token",Data);
        HashMap body = new HashMap();
        List<String> nameList  = new ArrayList<>();
        String result = "";
        for (String str : userIdList){
            body.put("userid",str);
            String doPost = UtilHttp.doPost("https://oapi.dingtalk.com/topapi/v2/user/get", null, params, body);
            ObjectMapper objectmapper = new ObjectMapper();
            String username = objectMapper.readTree(doPost)
                    .path("result")
                    .path("name")
                    .asText();
            nameList.add(username);
            result = nameList.stream()
                    .collect(Collectors.joining(","));
        }
        return result;
    }

    //文件存储方法
    /**
     * 下载文件到本地（自定义文件名）
     * param fileUrl 文件下载URL
     * param baseDir 基础存储目录
     * param customFileName 自定义文件名（不含扩展名）
     * return 下载后的文件绝对路径
*/    public static String downloadFile(String fileUrl,String baseDir,String customFileName) throws IOException{
        // 创建基础目录
        File baseDirectory = new File(baseDir);
        if (!baseDirectory.exists()) {
            baseDirectory.mkdirs();
        }

        // 完整的保存路径
        String savePath = new File(baseDir, customFileName).getAbsolutePath();

        // 下载文件
        URL url = new URL(fileUrl);
        URLConnection connection = url.openConnection();
        try (InputStream in = connection.getInputStream();
             FileOutputStream out = new FileOutputStream(savePath)) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        return savePath;
    }


    @Autowired
    private DDClient_Extension ddClientExtension;
    /*群消息卡片推送*/
    @SneakyThrows
    public McR createAndDeliverCard(@RequestBody JSONObject param){
        log.info("推送消息:{}",param);
        McException.assertParamException_Null(param,"cardData","outTrackId","openSpaceId","robotCode","cardTemplateId");
        Map<String,Object> data = new HashMap();
        data.put("imGroupOpenDeliverModel", UtilMap.map("robotCode",param.getString("robotCode")));
        /*卡片支持群搜索*/
        HashMap<String, Object> searchSupport  = new HashMap<>();
        searchSupport.put("searchTypeName","群卡片");
        String cardData = param.getString("cardData");
        // 1. 提取 JSON 部分（从第一个 '{' 到最后一个 '}'）
        int start = cardData.indexOf('{');
        int end = cardData.lastIndexOf('}');
        String jsonStr = cardData.substring(start, end + 1);
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(jsonStr);
        String nameTask = node.get("name_task").asText();       // "20260508测试"
        String nameCustomer = node.get("name_customer").asText(); // "客户A"
        String namePerson = node.get("name_person").asText();     // "鲜明阳，牧之"
        searchSupport.put("searchDesc",nameTask + nameCustomer + namePerson);
        data.put("imGroupOpenSpaceModel",UtilMap.map("supportForward, searchSupport",true,searchSupport));//增加查询条件
        if(param.containsKey("extInfo")){
            data.putAll(param.getJSONObject("extInfo"));
        }
        Map map = ddClientExtension.createAndDeliverCards(ddClient.getAccessToken(),param.getString("cardTemplateId"),param.getString("outTrackId"),
                UtilMap.map("cardParamMap",param.getJSONObject("cardData")),param.getString("openSpaceId"),data);
        return McR.success(map);
    }

    public static String generateHtmlLinks(String jsonArrayStr) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = mapper.readTree(jsonArrayStr);
        StringBuilder html = new StringBuilder();
        for (JsonNode node : root) {
            String url = node.get("arr").asText();
            // 生成 <a> 标签，链接地址和显示文字均为 URL
            html.append("<a href=\"").append(url).append("\">").append(url).append("</a>");
            html.append("<br/>");  // 换行
        }
        return html.toString();
    }

}
