package com.yifu.cloud.plus.v1.ekp.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yifu.cloud.plus.v1.ekp.config.WxConfig;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import lombok.extern.log4j.Log4j2;
import org.jasypt.commons.CommonUtils;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 企业微信智能表格调试工具类
 * 用于诊断和解决企业微信智能表格记录添加后不显示的问题
 */
@Log4j2
@Component
public class WeComSmartSheetDebugger {

    /**
     * 企业微信API基础URL
     */
    private static final String WE_COM_API_BASE_URL = "https://qyapi.weixin.qq.com/cgi-bin";

    /**
     * 获取access_token的接口路径
     */
    private static final String GET_TOKEN_PATH = "/gettoken";

    /**
     * 获取智能表格字段信息的接口路径
     */
    private static final String GET_FIELDS_PATH = "/wedoc/smartsheet/get_fields";

    /**
     * 添加记录的接口路径
     */
    private static final String ADD_RECORDS_PATH = "/wedoc/smartsheet/add_records";

    /**
     * 查询记录的接口路径
     */
    private static final String QUERY_RECORDS_PATH = "/wedoc/smartsheet/query_records";

    /**
     * 获取表格字段信息
     *
     * @param corpId     企业ID
     * @param corpSecret 应用的密钥
     * @param docId      文档ID
     * @param sheetId    工作表ID
     * @return 字段信息列表
     */
    public List<FieldInfo> getSheetFields(WxConfig wxConfig,String corpId, String corpSecret, String docId, String sheetId) {
        List<FieldInfo> fieldInfos = new ArrayList<>();
        try {
			RestTemplate restTemplate = new RestTemplate();
            // 1. 获取access_token
            String accessToken = getAccessToken(corpId, corpSecret);//wxConfig.getAccessToken(restTemplate);
            if (accessToken == null || accessToken.isEmpty()) {
                log.error("获取access_token失败");
                return fieldInfos;
            }

            // 2. 获取字段信息
            fieldInfos = fetchFields(accessToken, docId, sheetId);
        } catch (Exception e) {
            log.error("获取表格字段信息时发生异常: " + e.getMessage());
            e.printStackTrace();
        }
        return fieldInfos;
    }
	/**
	 * 获取表格字段信息
	 *
	 * @param accessToken accessToken
	 * @param docId      文档ID
	 * @param sheetId    工作表ID
	 * @return 字段信息列表
	 */
	public List<FieldInfo> getSheetFields(String accessToken,String docId, String sheetId) {
		List<FieldInfo> fieldInfos = new ArrayList<>();
		try {
			if (accessToken == null || accessToken.isEmpty()) {
				log.error("获取access_token失败");
				return fieldInfos;
			}

			// 2. 获取字段信息
			fieldInfos = fetchFields(accessToken, docId, sheetId);
		} catch (Exception e) {
			log.error("获取表格字段信息时发生异常: " + e.getMessage());
			e.printStackTrace();
		}
		return fieldInfos;
	}
    /**
     * 验证字段匹配性
     *
     * @param corpId     企业ID
     * @param corpSecret 应用的密钥
     * @param docId      文档ID
     * @param sheetId    工作表ID
     * @param records    要插入的记录列表
     * @return 不匹配的字段列表
     */
    public List<String> validateFields(WxConfig wxConfig,String corpId, String corpSecret, String docId, String sheetId,
                                       List<Map<String, Object>> records) {
        List<String> mismatches = new ArrayList<>();
        try {
            // 1. 获取表格字段信息
            List<FieldInfo> fieldInfos = getSheetFields(wxConfig,corpId, corpSecret, docId, sheetId);
            Map<String, FieldInfo> fieldMap = new HashMap<>();
            for (FieldInfo fieldInfo : fieldInfos) {
                fieldMap.put(fieldInfo.getTitle(), fieldInfo);
            }

            // 2. 检查记录中的字段
            for (Map<String, Object> record : records) {
                Map<String, Object> values = (Map<String, Object>) record.get("values");
                if (values != null) {
                    for (Map.Entry<String, Object> entry : values.entrySet()) {
                        String fieldName = entry.getKey();
                        Object fieldValue = entry.getValue();

                        // 检查字段是否存在
                        if (!fieldMap.containsKey(fieldName)) {
                            mismatches.add("字段 '" + fieldName + "' 在表格中不存在");
                            continue;
                        }

                        // 检查字段类型是否匹配
                        FieldInfo fieldInfo = fieldMap.get(fieldName);
                        String fieldType = fieldInfo.getType();
                        if (!isFieldTypeMatch(fieldType, fieldValue)) {
                            mismatches.add("字段 '" + fieldName + "' 类型不匹配，表格中为 " + fieldType +
                                    " 类型，但传入的是 " + fieldValue.getClass().getSimpleName() + " 类型");
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("验证字段匹配性时发生异常: " + e.getMessage());
            e.printStackTrace();
        }
        return mismatches;
    }
	/**
	 * 验证字段匹配性
	 *
	 * @param accessToken accessToken
	 * @param docId      文档ID
	 * @param sheetId    工作表ID
	 * @param records    要插入的记录列表
	 * @return 不匹配的字段列表
	 */
	public List<String> validateFields(String accessToken, String docId, String sheetId,
									   List<Map<String, Object>> records) {
		List<String> mismatches = new ArrayList<>();
		try {
			// 1. 获取表格字段信息
			List<FieldInfo> fieldInfos = getSheetFields(accessToken, docId, sheetId);
			Map<String, FieldInfo> fieldMap = new HashMap<>();
			for (FieldInfo fieldInfo : fieldInfos) {
				fieldMap.put(fieldInfo.getTitle(), fieldInfo);
			}

			// 2. 检查记录中的字段
			for (Map<String, Object> record : records) {
				Map<String, Object> values = (Map<String, Object>) record.get("values");
				if (values != null) {
					for (Map.Entry<String, Object> entry : values.entrySet()) {
						String fieldName = entry.getKey();
						Object fieldValue = entry.getValue();

						// 检查字段是否存在
						if (!fieldMap.containsKey(fieldName)) {
							mismatches.add("字段 '" + fieldName + "' 在表格中不存在");
							continue;
						}

						// 检查字段类型是否匹配
						FieldInfo fieldInfo = fieldMap.get(fieldName);
						String fieldType = fieldInfo.getType();
						if (!isFieldTypeMatch(fieldType, fieldValue)) {
							mismatches.add("字段 '" + fieldName + "' 类型不匹配，表格中为 " + fieldType +
									" 类型，但传入的是 " + fieldValue.getClass().getSimpleName() + " 类型");
						}
					}
				}
			}
		} catch (Exception e) {
			log.error("验证字段匹配性时发生异常: " + e.getMessage());
			e.printStackTrace();
		}
		return mismatches;
	}
    /**
     * 测试插入数据
     *
     * @param corpId     企业ID
     * @param corpSecret 应用的密钥
     * @param docId      文档ID
     * @param sheetId    工作表ID
     * @param records    要插入的记录列表
     * @return API响应结果
     */
    public String testInsertData(WxConfig wxConfig,String corpId, String corpSecret, String docId, String sheetId,
                                 List<Map<String, Object>> records) {
        try {
			RestTemplate restTemplate = new RestTemplate();
            // 1. 获取access_token
            String accessToken = getAccessToken(corpId, corpSecret);//wxConfig.getAccessToken(restTemplate);
            if (accessToken == null || accessToken.isEmpty()) {
                return "获取access_token失败";
            }

            // 2. 构造请求体
            JSONObject requestBody = new JSONObject();
            requestBody.put("docid", docId);
            requestBody.put("sheet_id", sheetId);
            requestBody.put("key_type", "CELL_VALUE_KEY_TYPE_FIELD_TITLE");

            // 构造records数组
			// 格式化
			JSONArray recordsArray = new JSONArray();

			for (Map<String, Object> fieldData : records) {
				JSONObject recordObj = new JSONObject();
				JSONObject values = new JSONObject();

				for (Map.Entry<String, Object> entry : fieldData.entrySet()) {
					String fieldName = entry.getKey();
					String fieldValue = entry.getValue().toString();

					// 构造字段值格式[{"type": "text", "text": "文本内容"}]
					JSONArray fieldValueArray = new JSONArray();
					JSONObject textObject = new JSONObject();
					textObject.put("type", "text");
					textObject.put("text", fieldValue);
					fieldValueArray.add(textObject);

					values.put(fieldName, fieldValueArray);
				}

				recordObj.put("values", values);
				recordsArray.add(recordObj);
			}

            requestBody.put("records", recordsArray);

            // 3. 发送请求
            return insertRecords(accessToken, requestBody);
        } catch (Exception e) {
            log.error("测试插入数据时发生异常: " + e.getMessage());
            e.printStackTrace();
            return "测试插入数据时发生异常: " + e.getMessage();
        }
    }
	/**
	 * 插入数据
	 *
	 * @param accessToken accessToken
	 * @param docId      文档ID
	 * @param sheetId    工作表ID
	 * @param records    要插入的记录列表
	 * @return API响应结果
	 */
	public String insertData(String accessToken, String docId, String sheetId,
								 List<Map<String, Object>> records,Map<String,String> fieldMap ) {
		try {
			if (accessToken == null || accessToken.isEmpty()) {
				return "获取access_token失败";
			}
			// 2. 构造请求体
			JSONObject requestBody = new JSONObject();
			requestBody.put("docid", docId);
			requestBody.put("sheet_id", sheetId);
			requestBody.put("key_type", "CELL_VALUE_KEY_TYPE_FIELD_TITLE");

			// 构造records数组
			// 格式化
			JSONArray recordsArray = new JSONArray();

			for (Map<String, Object> fieldData : records) {
				JSONObject recordObj = new JSONObject();
				JSONObject values = new JSONObject();

				for (Map.Entry<String, Object> entry : fieldData.entrySet()) {
					String fieldName = entry.getKey();
					String fieldValue = entry.getValue().toString();
					JSONArray fieldValueArray = new JSONArray();
					JSONObject textObject = new JSONObject();
					//根据fieldMap 对应的字段类型 初始化对应的企业微信的字段
					if (fieldMap.containsKey(fieldName)) {
						if (fieldMap.get(fieldName).equals("FIELD_TYPE_DATE_TIME")) {
							//时间格式转换,如果空则返回空，如果非空则转换为日期，然后返回时间戳字符串
							if (fieldValue.isEmpty()){
								fieldValue = "";
							}else {
								fieldValue = ""+DateUtil.stringToDate(fieldValue,DateUtil.ISO_EXPANDED_DATE_FORMAT).getTime();
							}
							values.put(fieldName, fieldValue);
						} else if (fieldMap.get(fieldName).equals("FIELD_TYPE_NUMBER")) {
							//如果是数字 字节转款，如果空或非数字 则返回0
							if (fieldValue.isEmpty() || !fieldValue.matches("^[0-9]+(\\.[0-9]+)?$")) {
								values.put(fieldName, 0);
							}else {
								values.put(fieldName, Double.valueOf(fieldValue));
							}
						} else {
							textObject.put("type", "text");
							textObject.put("text", fieldValue);
							fieldValueArray.add(textObject);
							values.put(fieldName, fieldValueArray);
						}
					}
				}
				recordObj.put("values", values);
				recordsArray.add(recordObj);
			}

			requestBody.put("records", recordsArray);

			// 3. 发送请求
			return insertRecords(accessToken, requestBody);
		} catch (Exception e) {
			log.error("测试插入数据时发生异常: " + e.getMessage());
			e.printStackTrace();
			return "测试插入数据时发生异常: " + e.getMessage();
		}
	}
    /**
     * 检查字段类型是否匹配
     *
     * @param fieldType  字段类型
     * @param fieldValue 字段值
     * @return 是否匹配
     */
    private boolean isFieldTypeMatch(String fieldType, Object fieldValue) {
        switch (fieldType) {
            case "number":
                return fieldValue instanceof Number;
            case "text":
                return fieldValue instanceof String;
            case "boolean":
                return fieldValue instanceof Boolean;
            default:
                // 其他类型默认允许
                return true;
        }
    }

    /**
     * 获取企业微信access_token
     *
     * @param corpId     企业ID
     * @param corpSecret 应用密钥
     * @return access_token
     */
    private String getAccessToken(String corpId, String corpSecret) {
        try {
            String url = WE_COM_API_BASE_URL + GET_TOKEN_PATH + "?corpid=" + corpId + "&corpsecret=" + corpSecret;

            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);

            if (response.getStatusCode() == HttpStatus.OK) {
                JSONObject jsonObject = JSON.parseObject(response.getBody());
                if (jsonObject.getInteger("errcode") == 0) {
                    return jsonObject.getString("access_token");
                } else {
                    log.error("获取access_token失败，错误代码：" + jsonObject.getInteger("errcode")
                            + "，错误信息：" + jsonObject.getString("errmsg"));
                    return null;
                }
            }
        } catch (Exception e) {
            log.error("获取access_token时发生异常: " + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取字段信息
     *
     * @param accessToken 访问令牌
     * @param docId       文档ID
     * @param sheetId     工作表ID
     * @return 字段信息列表
     */
    private List<FieldInfo> fetchFields(String accessToken, String docId, String sheetId) {
        List<FieldInfo> fieldInfos = new ArrayList<>();
        try {
            String url = WE_COM_API_BASE_URL + GET_FIELDS_PATH + "?access_token=" + accessToken;

            RestTemplate restTemplate = new RestTemplate();

            // 构造请求体
            JSONObject requestBody = new JSONObject();
            requestBody.put("docid", docId);
            requestBody.put("sheet_id", sheetId);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            HttpEntity<String> request = new HttpEntity<>(requestBody.toJSONString(), headers);
            ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);

            if (response.getStatusCode() == HttpStatus.OK) {
                JSONObject jsonObject = JSON.parseObject(response.getBody());
                if (jsonObject.getInteger("errcode") == 0) {
                    JSONArray fields = jsonObject.getJSONArray("fields");
                    if (fields != null && !fields.isEmpty()) {
                        for (int i = 0; i < fields.size(); i++) {
                            JSONObject field = fields.getJSONObject(i);
                            FieldInfo fieldInfo = new FieldInfo();
                            fieldInfo.setFieldId(field.getString("field_id"));
                            fieldInfo.setTitle(field.getString("field_title"));
                            fieldInfo.setType(field.getString("field_type"));
                            fieldInfos.add(fieldInfo);
                        }
                    }
                } else {
                    log.error("获取字段信息失败，错误代码：" + jsonObject.getInteger("errcode")
                            + "，错误信息：" + jsonObject.getString("errmsg"));
                }
            }
        } catch (Exception e) {
            log.error("获取字段信息时发生异常: " + e.getMessage());
            e.printStackTrace();
        }
        return fieldInfos;
    }

    /**
     * 插入记录
     *
     * @param accessToken 访问令牌
     * @param requestBody 请求体
     * @return API响应结果
     */
    private String insertRecords(String accessToken, JSONObject requestBody) {
        try {
            String url = WE_COM_API_BASE_URL + ADD_RECORDS_PATH + "?access_token=" + accessToken;

            RestTemplate restTemplate = new RestTemplate();

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            HttpEntity<String> request = new HttpEntity<>(requestBody.toJSONString(), headers);
			//log.info("插入数据的JSON：" + request.getBody());
            ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);

            return response.getBody();
        } catch (Exception e) {
            log.error("插入记录时发生异常: " + e.getMessage());
            e.printStackTrace();
            return "插入记录时发生异常: " + e.getMessage();
        }
    }

    /**
     * 字段信息内部类
     */
    public static class FieldInfo {
        private String fieldId;
        private String title;
        private String type;

        public String getFieldId() {
            return fieldId;
        }

        public void setFieldId(String fieldId) {
            this.fieldId = fieldId;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        @Override
        public String toString() {
            return "FieldInfo{" +
                    "fieldId='" + fieldId + '\'' +
                    ", title='" + title + '\'' +
                    ", type='" + type + '\'' +
                    '}';
        }
    }
    
    /**
     * 构造符合企业微信智能表格要求的记录数据
     * 
     * @param docId 文档ID
     * @param sheetId 工作表ID
     * @param fieldDataList 字段数据列表，每个元素是一个Map，key为字段名，value为字段值
     * @return 符合要求的JSON字符串
     */
    public String buildRecordData(String docId, String sheetId, List<Map<String, String>> fieldDataList) {
        JSONObject requestBody = new JSONObject();
        requestBody.put("docid", docId);
        requestBody.put("sheet_id", sheetId);
        requestBody.put("key_type", "CELL_VALUE_KEY_TYPE_FIELD_TITLE");

        JSONArray recordsArray = new JSONArray();
        
        for (Map<String, String> fieldData : fieldDataList) {
            JSONObject recordObj = new JSONObject();
            JSONObject values = new JSONObject();
            
            for (Map.Entry<String, String> entry : fieldData.entrySet()) {
                String fieldName = entry.getKey();
                String fieldValue = entry.getValue();
                
                // 构造字段值格式[{"type": "text", "text": "文本内容"}]
                JSONArray fieldValueArray = new JSONArray();
                JSONObject textObject = new JSONObject();
                textObject.put("type", "text");
                textObject.put("text", fieldValue);
                fieldValueArray.add(textObject);
                
                values.put(fieldName, fieldValueArray);
            }
            
            recordObj.put("values", values);
            recordsArray.add(recordObj);
        }
        
        requestBody.put("records", recordsArray);
        return requestBody.toJSONString();
    }
}