package com.openhis.web.document.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.openhis.web.document.appservice.IDocStatisticsDefinitionAppService;
import com.openhis.web.document.dto.DocRecordDto;
import com.openhis.web.document.dto.DocStatisticsDefinitionDto;
import com.openhis.web.document.dto.DocStatisticsDto;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.core.framework.datasource.DynamicDataSourceContextHolder.log;

@Component
public class ConvertToDocStatistics {
    @Resource
    IDocStatisticsDefinitionAppService docStatisticsDefinitionAppService;

    /**
     * 将文档记录转换为统计DTO列表的工具方法
     * 支持两种JSON结构：
     * 1. 简单键值对：{"目标code": 值, "recordTime": "yyyy-MM-dd HH:mm:ss"}
     * 2. 嵌套Item列表：{"目标code+Item": [{"目标code": 值1}, {"目标code": 值2}],"recordTime": "yyyy-MM-dd HH:mm:ss"}
     * 3. 记录 Time 字段：{"目标code+Item": [{"目标code": 值1, "recordTime": "yyyy-MM-dd HH:mm:ss"}, {"目标code": 值2, "recordTime": "yyyy-MM-dd HH:mm:ss"}]}
     * 4. 记录 Time 字段：{"目标code": 值, "recordTime": "yyyy-MM-dd HH:mm:ss", "目标code+Item": [{"目标code": 值1, "recordTime": "yyyy-MM-dd HH:mm:ss"}, {"目标code": 值2, "recordTime": "yyyy-MM-dd HH:mm:ss"}]}
     * 日期类型使用java.util.Date
     */
    public List<DocStatisticsDto> convertToStatisticsDtoList(DocRecordDto docRecordDto) {
        // 初始化返回的统计DTO列表
        List<DocStatisticsDto> statisticsDtoList = new ArrayList<>();

        // 防御性判断：如果文档记录为空，直接返回空列表
        if (docRecordDto == null) {
            return statisticsDtoList;
        }

        // 获取JSON格式的内容字符串（待解析的原始数据）
        String contentJson = docRecordDto.getContentJson();
        // 获取系统中定义的统计项列表（需要解析的目标code集合）
        List<DocStatisticsDefinitionDto> definitionList = docStatisticsDefinitionAppService.getList(1);

        // 防御性判断：如果统计项定义为空，直接返回空列表
        if (definitionList == null || definitionList.isEmpty()) {
            return statisticsDtoList;
        }

        // 解析JSON字符串为JSONObject（方便操作嵌套结构）
        JSONObject contentJsonObj = parseJson(contentJson);
        // 如果JSON解析失败（返回null），直接返回空列表
        if (contentJsonObj == null) {
            return statisticsDtoList;
        }

        // 遍历每个统计项定义，解析对应的值
        for (DocStatisticsDefinitionDto definition : definitionList) {
            // 当前需要解析的目标字段code（如"BQ"、"DrugCode"）
            String targetCode = definition.getCode();

            // 场景1：先尝试解析顶级键值对结构（如{"BQ": 123}）
            if (contentJsonObj.containsKey(targetCode)) {
                // 提取值并转换为字符串
                String value = String.valueOf(contentJsonObj.get(targetCode));
                Date recordTime = docRecordDto.getRecordTime();
                // 创建DTO并添加到结果列表
                addSingleDto(statisticsDtoList, definition, docRecordDto, value,
                        recordTime);
                // 处理完当前统计项，继续下一个
                continue;
            }

            // 场景2：如果顶级键不存在，尝试解析嵌套的Item列表
            // 列表字段名规则：目标code + "Item"（如code=BQ → 列表字段名=BQItem）
            String itemListKey = targetCode + "Item";
            // 从JSON中获取对应的列表
            JSONArray itemArray = contentJsonObj.getJSONArray(itemListKey);

            // 判断列表是否存在且不为空
            if (itemArray != null && !itemArray.isEmpty()) {
                // 遍历列表中的每个元素（每个元素是一个JSONObject）
                for (int i = 0; i < itemArray.size(); i++) {
                    JSONObject itemObj = itemArray.getJSONObject(i);
                    // 检查元素是否包含目标code
                    if (itemObj != null && itemObj.containsKey(targetCode)) {
                        // 提取当前元素的目标值
                        String value = String.valueOf(itemObj.get(targetCode));
                        Date recordTime = new Date();
                        if (itemObj.containsKey("recordTime")) {
                            recordTime = itemObj.getDate("recordTime");
                        } else if (contentJsonObj.containsKey("recordTime")) {
                            recordTime = contentJsonObj.getDate("recordTime");
                        } else {
                            recordTime = docRecordDto.getRecordTime();
                        }
                        // 创建DTO并添加到结果列表
                        addSingleDto(statisticsDtoList, definition, docRecordDto, value,
                                recordTime);
                    }
                }
                // 日志提示：如果列表存在但未找到匹配的code
                if (statisticsDtoList.isEmpty()) {
                    log.warn("列表{}中未找到包含{}的元素，可能数据格式不匹配", itemListKey, targetCode);
                }
            } else {
                // 日志提示：未找到对应的Item列表或列表为空
                log.error("未找到列表{}或列表为空，无法解析统计项: {}", itemListKey, targetCode);
            }
        }

        return statisticsDtoList;
    }

    /**
     * 工具方法：解析JSON字符串为JSONObject
     *
     * @param jsonStr 原始JSON字符串
     * @return 解析后的JSONObject，失败则返回null
     */
    private JSONObject parseJson(String jsonStr) {
        // 如果JSON字符串为空，直接返回null
        if (jsonStr == null) {
            return null;
        }
        try {
            // 解析JSON字符串
            return JSON.parseObject(jsonStr);
        } catch (Exception e) {
            // 记录解析异常日志
            log.error("JSON解析失败，原始字符串: {}", jsonStr, e);
            return null;
        }
    }

    /**
     * 工具方法：创建单个统计DTO并添加到列表
     *
     * @param dtoList      目标DTO列表
     * @param definition   统计项定义
     * @param docRecordDto 文档记录DTO
     * @param value        解析出的统计值
     * @param recordTime   记录时间
     */
    private void addSingleDto(List<DocStatisticsDto> dtoList,
                              DocStatisticsDefinitionDto definition,
                              DocRecordDto docRecordDto,
                              String value,
                              Date recordTime) {
        // 创建统计DTO对象
        DocStatisticsDto dto = new DocStatisticsDto();
        // 设置统计值和关联的统计项定义信息
        dto.setValue(value);
        dto.setStatisticDefinitionCode(definition.getCode());
        dto.setStatisticDefinitionId(definition.getId());
        // 设置关联的文档记录信息
        dto.setRecordId(docRecordDto.getId());
        dto.setEncounterId(docRecordDto.getEncounterId());
        dto.setPatientId(docRecordDto.getPatientId());
        dto.setOrganizationId(docRecordDto.getOrganizationId());
        dto.setRecordTime(recordTime);
        dto.setSource(docRecordDto.getSource());
        // 将创建好的DTO添加到结果列表
        dtoList.add(dto);
    }

}
