package com.common.service.impl;

import com.common.entity.*;
import com.common.mapper.*;
import com.common.service.AnalysisEngine;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 实时分析引擎实现（达梦安全版适配）
 *
 * 与 RealtimeAnalysisEngine 功能完全相同，唯一差异：
 * 注入 SqlGeneratorServiceImplDm（子查询包装模式SQL生成器），
 * 以适配达梦安全版数据库 GROUP BY 不支持自定义函数（TUMBLE/HOP/SESSION）的问题。
 *
 * 通过 @ConditionalOnProperty 与 RealtimeAnalysisEngine 二选一注册，
 * 由配置 analysis.db.dameng-subquery-mode=true 激活本实现。
 *
 * @see RealtimeAnalysisEngine 原始实现（平铺SQL模式）
 * @see SqlGeneratorServiceImplDm 子查询包装SQL生成器
 */
@Slf4j
@Service("realtimeAnalysisEngine")
@org.springframework.boot.autoconfigure.condition.ConditionalOnProperty(
        name = "analysis.db.dameng-subquery-mode",
        havingValue = "true")
public class RealtimeAnalysisEngineDm implements AnalysisEngine {

    // 直接实例化（非Spring Bean），避免与父类SqlGeneratorServiceImpl产生类型冲突
    private final SqlGeneratorServiceImplDm sqlGeneratorService = new SqlGeneratorServiceImplDm();

    @Autowired
    private AnalysisAnalysisRuleMapper ruleMapper;

    @Autowired
    private AnalysisFieldMapper fieldMapper;

    @Autowired
    private AnalysisWhereConditionMapper whereConditionMapper;

    @Autowired
    private AnalysisGroupByColumnMapper groupByColumnMapper;

    @Autowired
    private AnalysisGroupByWindowMapper groupByWindowMapper;


    @Autowired
    private AnalysisFilterMapper filterMapper;

    @Autowired
    private AnalysisGroupByHavingMapper groupByHavingMapper;

    @Autowired
    private AnalysisTaskHistoryMapper taskHistoryMapper;

    @Autowired
    private AlarmMapper alarmMapper;
    @Autowired
    private AnalysisGroupByMapper groupByMapper;
    @Autowired
    private JdbcTemplate jdbcTemplate;

    private static final String RUN_MODE = "realtime";
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public Map<String, Object> executeRule(AnalysisAnalysisRule rule) {
        String batchNo = generateBatchNo();
        LocalDateTime startTime = LocalDateTime.now().withSecond(0).withNano(0);
        LocalDateTime dataEndTime = startTime;

        // 加载分组和窗口配置（在计算时间范围之前）
        AnalysisGroupByWindow groupByWindow = null;
        List<AnalysisGroupBy> groupByList = groupByMapper.selectByRuleId(rule.getRuleId());
        if (groupByList != null && !groupByList.isEmpty()) {
            AnalysisGroupBy groupBy = groupByList.get(0);
            if (groupBy.getId() != null) {
                groupByWindow = groupByWindowMapper.selectByGroupById(groupBy.getId().intValue());
            }
        }

        // 根据窗口类型动态计算数据查询时间范围
        LocalDateTime dataStartTime = calculateDataStartTime(dataEndTime, groupByWindow);

        log.info("开始执行实时规则(DM子查询模式): ruleId={}, ruleName={}, batchNo={}, windowType={}, dataStartTime={}, dataEndTime={}",
                rule.getRuleId(), rule.getRuleName(), batchNo,
                groupByWindow != null ? groupByWindow.getWindowType() : "NONE",
                dataStartTime.format(DATE_FORMATTER),
                dataEndTime.format(DATE_FORMATTER));

        // 创建任务历史记录
        AnalysisTaskHistory history = AnalysisTaskHistory.builder()
                .id(System.currentTimeMillis())
                .ruleId(rule.getRuleId())
                .startTime(startTime)
                .status("RUNNING")
                .progressPercent(0)
                .inputCount(0L)
                .outputCount(0L)
                .delFlag("0")
                .createTime(startTime)
                .updateTime(startTime)
                .tenantId("000000")
                .remark("实时分析任务(达梦适配) - " + batchNo)
                .build();
        taskHistoryMapper.insert(history);

        Map<String, Object> result = new HashMap<>();
        result.put("ruleId", rule.getRuleId());
        result.put("ruleName", rule.getRuleName());
        result.put("runMode", RUN_MODE);
        result.put("batchNo", batchNo);

        try {
            // 更新规则状态为运行中
            ruleMapper.updateTaskStatus(rule.getRuleId(), "running", 1L);

            // 加载规则配置
            List<AnalysisField> fields = fieldMapper.selectByRuleId(rule.getRuleId());
            List<AnalysisWhereCondition> whereConditions = whereConditionMapper.selectByRuleId(rule.getRuleId());
            List<AnalysisFilter> filters = filterMapper.selectByRuleId(rule.getRuleId());
            List<AnalysisGroupByColumn> groupByColumns = groupByColumnMapper.selectByRuleId(rule.getRuleId());
            List<AnalysisGroupByHaving> havingConditions = groupByHavingMapper.selectByRuleId(rule.getRuleId());

            // 生成SQL（调用达梦适配版SQL生成器，子查询包装模式）
            String sql = sqlGeneratorService.generateSql(
                    rule,
                    fields,
                    whereConditions,
                    filters,
                    groupByColumns,
                    havingConditions,
                    groupByWindow,
                    dataStartTime.format(DATE_FORMATTER),
                    dataEndTime.format(DATE_FORMATTER)
            );

            log.info("生成的SQL(达梦子查询模式): {}", sql);

            // 执行SQL
            List<Map<String, Object>> queryResult = jdbcTemplate.queryForList(sql);
            result.put("queryResult", queryResult);

            // 处理结果，生成告警
            long alarmCount = 0;
            if (!queryResult.isEmpty()) {
                List<Alarm> alarms = convertToAlarms(rule, queryResult);
                if (!alarms.isEmpty()) {
                    String tableName = "alarm";
                    alarmMapper.batchInsert(alarms);
                    alarmCount = alarms.size();
                }
            }

            // 更新任务历史
            LocalDateTime endTime = LocalDateTime.now();
            long durationSeconds = java.time.Duration.between(startTime, endTime).getSeconds();
            history.setEndTime(endTime);
            history.setDurationTime(durationSeconds);
            history.setProgressPercent(100);
            history.setInputCount((long) queryResult.size());
            history.setOutputCount(alarmCount);
            history.setStatus("COMPLETED");
            history.setUpdateTime(endTime);
            taskHistoryMapper.update(history);

            result.put("processedCount", queryResult.size());
            result.put("alarmCount", alarmCount);
            result.put("status", "success");

            // 更新规则状态为等待
            ruleMapper.updateTaskStatus(rule.getRuleId(), "waiting", 1L);

            log.info("规则执行成功(达梦子查询模式): ruleId={}, processedCount={}, alarmCount={}",
                    rule.getRuleId(), queryResult.size(), alarmCount);

        } catch (Exception e) {
            log.error("规则执行失败: ruleId={}", rule.getRuleId(), e);

            // 更新任务历史
            LocalDateTime endTime = LocalDateTime.now();
            long durationSeconds = java.time.Duration.between(startTime, endTime).getSeconds();
            history.setEndTime(endTime);
            history.setDurationTime(durationSeconds);
            history.setStatus("FAILED");
            history.setRemark("执行失败: " + (e.getMessage().length() > 480 ? e.getMessage().substring(0, 480) : e.getMessage()));
            history.setUpdateTime(endTime);
            taskHistoryMapper.update(history);

            // 更新规则状态
            ruleMapper.updateTaskStatus(rule.getRuleId(), "stopped", 1L);

            result.put("status", "failed");
            result.put("errorMsg", e.getMessage());
        }

        return result;
    }

    @Override
    public List<Map<String, Object>> executeRules(List<AnalysisAnalysisRule> rules) {
        List<Map<String, Object>> results = new ArrayList<>();

        for (AnalysisAnalysisRule rule : rules) {
            try {
                Map<String, Object> result = executeRule(rule);
                results.add(result);
            } catch (Exception e) {
                log.error("执行规则失败: ruleId={}", rule.getRuleId(), e);
                Map<String, Object> errorResult = new HashMap<>();
                errorResult.put("ruleId", rule.getRuleId());
                errorResult.put("ruleName", rule.getRuleName());
                errorResult.put("status", "failed");
                errorResult.put("errorMsg", e.getMessage());
                results.add(errorResult);
            }
        }

        return results;
    }

    @Override
    public void stopRule(String ruleId) {
        try {
            ruleMapper.updateTaskStatus(ruleId, "stopped", 1L);
            log.info("已停止规则: ruleId={}", ruleId);
        } catch (Exception e) {
            log.error("停止规则失败: ruleId={}", ruleId, e);
        }
    }

    @Override
    public String getRunMode() {
        return RUN_MODE;
    }

    /**
     * 生成批次号
     */
    private String generateBatchNo() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
    }

    /**
     * 根据窗口类型动态计算数据查询开始时间
     */
    private LocalDateTime calculateDataStartTime(LocalDateTime dataEndTime, AnalysisGroupByWindow groupByWindow) {
        if (groupByWindow == null) {
            log.warn("未配置窗口类型，使用默认查询范围：最近30分钟");
            return dataEndTime.minusMinutes(30);
        }

        String windowType = groupByWindow.getWindowType();

        if (windowType == null || windowType.trim().isEmpty()) {
            log.warn("窗口类型为空，使用默认查询范围：最近30分钟");
            return dataEndTime.minusMinutes(30);
        }

        switch (windowType.toUpperCase()) {
            case "TUMBLE":
                return calculateTumbleWindowStartTime(dataEndTime, groupByWindow);
            case "HOP":
                return calculateHopWindowStartTime(dataEndTime, groupByWindow);
            case "SESSION":
                return calculateSessionWindowStartTime(dataEndTime, groupByWindow);
            default:
                log.warn("未知窗口类型: {}，使用默认查询范围：最近30分钟", windowType);
                return dataEndTime.minusMinutes(30);
        }
    }

    /**
     * 计算滚动窗口的数据查询开始时间
     */
    private LocalDateTime calculateTumbleWindowStartTime(LocalDateTime dataEndTime, AnalysisGroupByWindow groupByWindow) {
        Integer windowSize = groupByWindow.getTumbleWindowSize();
        String windowSizeUnit = groupByWindow.getTumbleWindowSizeUnit();

        if (windowSize == null || windowSize <= 0) {
            log.warn("滚动窗口大小配置无效，使用默认值：5分钟");
            windowSize = 5;
            windowSizeUnit = "m";
        }

        if (windowSizeUnit == null || windowSizeUnit.trim().isEmpty()) {
            windowSizeUnit = "m";
        }

        LocalDateTime dataStartTime;
        switch (windowSizeUnit.toLowerCase()) {
            case "s":
                dataStartTime = dataEndTime.minusSeconds(windowSize);
                break;
            case "m":
                dataStartTime = dataEndTime.minusMinutes(windowSize);
                break;
            case "h":
                dataStartTime = dataEndTime.minusHours(windowSize);
                break;
            case "d":
                dataStartTime = dataEndTime.minusDays(windowSize);
                break;
            default:
                log.warn("滚动窗口单位无效: {}，使用默认单位：分钟", windowSizeUnit);
                dataStartTime = dataEndTime.minusMinutes(windowSize);
        }

        log.info("滚动窗口查询范围: 窗口大小={}{}，查询时间范围=[{}, {}]",
                windowSize, windowSizeUnit,
                dataStartTime.format(DATE_FORMATTER),
                dataEndTime.format(DATE_FORMATTER));

        return dataStartTime;
    }

    /**
     * 计算滑动窗口的数据查询开始时间
     */
    private LocalDateTime calculateHopWindowStartTime(LocalDateTime dataEndTime, AnalysisGroupByWindow groupByWindow) {
        Integer windowSize = groupByWindow.getHopWindowSize();
        String windowSizeUnit = groupByWindow.getHopWindowSizeUnit();

        if (windowSize == null || windowSize <= 0) {
            log.warn("滑动窗口大小配置无效，使用默认值：5分钟");
            windowSize = 5;
            windowSizeUnit = "m";
        }

        if (windowSizeUnit == null || windowSizeUnit.trim().isEmpty()) {
            windowSizeUnit = "m";
        }

        LocalDateTime dataStartTime;
        switch (windowSizeUnit.toLowerCase()) {
            case "s":
                dataStartTime = dataEndTime.minusSeconds(windowSize);
                break;
            case "m":
                dataStartTime = dataEndTime.minusMinutes(windowSize);
                break;
            case "h":
                dataStartTime = dataEndTime.minusHours(windowSize);
                break;
            case "d":
                dataStartTime = dataEndTime.minusDays(windowSize);
                break;
            default:
                log.warn("滑动窗口单位无效: {}，使用默认单位：分钟", windowSizeUnit);
                dataStartTime = dataEndTime.minusMinutes(windowSize);
        }

        log.info("滑动窗口查询范围: 窗口大小={}{}，查询时间范围=[{}, {}]",
                windowSize, windowSizeUnit,
                dataStartTime.format(DATE_FORMATTER),
                dataEndTime.format(DATE_FORMATTER));

        return dataStartTime;
    }

    /**
     * 计算会话窗口的数据查询开始时间
     */
    private LocalDateTime calculateSessionWindowStartTime(LocalDateTime dataEndTime, AnalysisGroupByWindow groupByWindow) {
        Integer sessionTimeout = groupByWindow.getSessionWindowSize();
        String sessionTimeoutUnit = groupByWindow.getSessionWindowSizeUnit();

        if (sessionTimeout == null || sessionTimeout <= 0) {
            log.warn("会话窗口超时时间配置无效，使用默认值：30分钟");
            sessionTimeout = 30;
            sessionTimeoutUnit = "m";
        }

        if (sessionTimeoutUnit == null || sessionTimeoutUnit.trim().isEmpty()) {
            sessionTimeoutUnit = "m";
        }

        LocalDateTime dataStartTime;
        switch (sessionTimeoutUnit.toLowerCase()) {
            case "s":
                dataStartTime = dataEndTime.minusSeconds(sessionTimeout);
                break;
            case "m":
                dataStartTime = dataEndTime.minusMinutes(sessionTimeout);
                break;
            case "h":
                dataStartTime = dataEndTime.minusHours(sessionTimeout);
                break;
            case "d":
                dataStartTime = dataEndTime.minusDays(sessionTimeout);
                break;
            default:
                log.warn("会话窗口超时单位无效: {}，使用默认单位：分钟", sessionTimeoutUnit);
                dataStartTime = dataEndTime.minusMinutes(sessionTimeout);
        }

        // 会话窗口额外增加1天缓冲时间
        dataStartTime = dataStartTime.minusDays(1);

        log.info("会话窗口查询范围: 超时时间={}{}，额外缓冲1天，查询时间范围=[{}, {}]",
                sessionTimeout, sessionTimeoutUnit,
                dataStartTime.format(DATE_FORMATTER),
                dataEndTime.format(DATE_FORMATTER));

        return dataStartTime;
    }

    /**
     * 转换查询结果为告警对象
     */
    private List<Alarm> convertToAlarms(AnalysisAnalysisRule rule, List<Map<String, Object>> queryResult) {
        List<Alarm> alarms = new ArrayList<>();

        for (Map<String, Object> row : queryResult) {
            Alarm alarm = Alarm.builder()
                    .id(UUID.randomUUID().toString())
                    .createdAt(LocalDateTime.now())
                    .updatedAt(LocalDateTime.now())
                    .alarmName(rule.getRuleName())
                    .engineType("realtime")
                    .attackResult(-1)
                    .focused(false)
                    .fall(0)
                    .alarmLevel("未知")
                    .baseFocused(false)
                    .isUpdated(false)
                    .alarmSource(1)
                    .dispositionAdvice("研判后处置")
                    .disposedState(0)
                    .attackDirection("other")
                    .etlTime(LocalDateTime.now())
                    .alarmAreaId(0)
                    .comment(buildComment(row))
                    .attackChainPhase(getIntegerArray(-1))
                    .judgedState(0)
                    .build();

            // 映射查询结果字段到告警对象
            if (row.containsKey("log_start_at")) {
                alarm.setLogStartAt(getTimestampValue(row.get("log_start_at")));
            }
            if (row.containsKey("log_end_at")) {
                alarm.setLogEndAt(getTimestampValue(row.get("log_end_at")));
            }
            if (row.containsKey("alarm_name")) {
                alarm.setAlarmName(getStringValue(row.get("alarm_name")));
            }
            if (row.containsKey("alarm_type")) {
                alarm.setAlarmType(getStringValue(row.get("alarm_type")));
            }
            if (row.containsKey("alarm_level")) {
                alarm.setAlarmLevel(convertAlarmLevel(getIntegerValue(row.get("alarm_level"))));
            }
            if (row.containsKey("attack_ip")) {
                alarm.setAttackIp(getStringArray(row.get("attack_ip")));
            }
            if (row.containsKey("victim_ip")) {
                alarm.setVictimIp(getStringArray(row.get("victim_ip")));
            }
            if (row.containsKey("victim_web_url")) {
                alarm.setVictimWebUrl(getStringArray(row.get("victim_web_url")));
            }
            if (row.containsKey("attack_chain_phase")) {
                alarm.setAttackChainPhase(getIntegerArray(row.get("attack_chain_phase")));
            }
            if (row.containsKey("device_id")) {
                alarm.setDeviceId(getIntegerArray(row.get("device_id")));
            }
            if (row.containsKey("tag")) {
                alarm.setTag(getStringArray(row.get("tag")));
            }
            if (row.containsKey("comment")) {
                alarm.setComment(getStringValue(row.get("comment")));
            }
            if (row.containsKey("origin_log_ids")) {
                alarm.setOriginLogIds(getStringArray(row.get("origin_log_ids")));
            }
            if (row.containsKey("query_id")) {
                alarm.setQueryId(getStringValue(row.get("query_id")));
            }
            if (row.containsKey("attack_result")) {
                alarm.setAttackResult(getIntegerValue(row.get("attack_result")));
            }
            if (row.containsKey("fall")) {
                alarm.setFall(getIntegerValue(row.get("fall")));
            }
            if (row.containsKey("payload")) {
                alarm.setPayload(getBytesValue(row.get("payload")));
            }
            if (row.containsKey("operate_event")) {
                alarm.setOperateEvent(getIntegerArray(row.get("operate_event")));
            }
            if (row.containsKey("attack_port")) {
                alarm.setAttackPort(getIntegerArray(row.get("attack_port")));
            }
            if (row.containsKey("victim_port")) {
                alarm.setVictimPort(getIntegerArray(row.get("victim_port")));
            }
            if (row.containsKey("attack_method")) {
                alarm.setAttackMethod(getStringValue(row.get("attack_method")));
            }
            if (row.containsKey("business_ext")) {
                alarm.setBusinessExt(getStringValue(row.get("business_ext")));
            }
            if (row.containsKey("http_status")) {
                alarm.setHttpStatus(getStringValue(row.get("http_status")));
            }
            if (row.containsKey("dns_info")) {
                alarm.setDnsInfo(getStringValue(row.get("dns_info")));
            }
            if (row.containsKey("account_info")) {
                alarm.setAccountInfo(getStringValue(row.get("account_info")));
            }
            if (row.containsKey("attacker_info")) {
                alarm.setAttackerInfo(getStringValue(row.get("attacker_info")));
            }
            if (row.containsKey("victim_info")) {
                alarm.setVictimInfo(getStringValue(row.get("victim_info")));
            }
            if (row.containsKey("suspicious_action")) {
                alarm.setSuspiciousAction(getStringValue(row.get("suspicious_action")));
            }
            if (row.containsKey("vuln_info")) {
                alarm.setVulnInfo(getStringValue(row.get("vuln_info")));
            }
            if (row.containsKey("weak_pwd")) {
                alarm.setWeakPwd(getStringValue(row.get("weak_pwd")));
            }
            if (row.containsKey("compliance_baseline")) {
                alarm.setComplianceBaseline(getStringValue(row.get("compliance_baseline")));
            }
            if (row.containsKey("file_info")) {
                alarm.setFileInfo(getStringValue(row.get("file_info")));
            }
            if (row.containsKey("file_tags")) {
                alarm.setFileTags(getStringValue(row.get("file_tags")));
            }
            if (row.containsKey("endpoint_info")) {
                alarm.setEndpointInfo(getStringValue(row.get("endpoint_info")));
            }
            if (row.containsKey("origin_info")) {
                alarm.setOriginInfo(getStringValue(row.get("origin_info")));
            }
            if (row.containsKey("protocol_info")) {
                alarm.setProtocolInfo(getStringValue(row.get("protocol_info")));
            }
            if (row.containsKey("email_info")) {
                alarm.setEmailInfo(getStringValue(row.get("email_info")));
            }
            if (row.containsKey("sensitive_data")) {
                alarm.setSensitiveData(getStringValue(row.get("sensitive_data")));
            }
            if (row.containsKey("hit_intelligence")) {
                alarm.setHitIntelligence(getIntegerValue(row.get("hit_intelligence")));
            }
            if (row.containsKey("window_time")) {
                alarm.setWindowTime(getStringValue(row.get("window_time")));
            }
            if (row.containsKey("attack_ip_pic")) {
                alarm.setAttackIpPic(getStringValue(row.get("attack_ip_pic")));
            }
            if (row.containsKey("victim_ip_pic")) {
                alarm.setVictimIpPic(getStringValue(row.get("victim_ip_pic")));
            }
            if (row.containsKey("operation_at")) {
                alarm.setOperationAt(getTimestampValue(row.get("operation_at")));
            }
            if (row.containsKey("attack_direction")) {
                alarm.setAttackDirection(getStringValue(row.get("attack_direction")));
            }
            if (row.containsKey("etl_time")) {
                alarm.setEtlTime(getTimestampValue(row.get("etl_time")));
            }
            if (row.containsKey("log_count")) {
                alarm.setLogCount(getIntegerValue(row.get("log_count")));
            }
            if (row.containsKey("is_asset_hit")) {
                alarm.setIsAssetHit(getIntegerValue(row.get("is_asset_hit")));
            }
            if (row.containsKey("http_req_header")) {
                alarm.setHttpReqHeader(getStringArray(row.get("http_req_header")));
            }
            if (row.containsKey("http_req_body")) {
                alarm.setHttpReqBody(getStringArray(row.get("http_req_body")));
            }
            if (row.containsKey("http_resp_header")) {
                alarm.setHttpRespHeader(getStringArray(row.get("http_resp_header")));
            }
            if (row.containsKey("http_resp_body")) {
                alarm.setHttpRespBody(getStringArray(row.get("http_resp_body")));
            }
            if (row.containsKey("window_time")) {
                alarm.setLogEndAt(getTimestampValue(row.get("window_time")));
            }
            alarms.add(alarm);
        }

        return alarms;
    }

    private byte[] getBytesValue(Object value) {
        if (value == null) {
            return null;
        }
        if (value instanceof byte[]) {
            return (byte[]) value;
        }
        return value.toString().getBytes();
    }

    private String getStringValue(Object value) {
        if (value == null) {
            return null;
        }
        return value.toString();
    }

    private Long getLongValue(Object value) {
        if (value == null) {
            return 0L;
        }
        if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        return Long.parseLong(value.toString());
    }

    private Integer getIntegerValue(Object value) {
        if (value == null) {
            return -1;
        }
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        return Integer.parseInt(value.toString());
    }

    private LocalDateTime getTimestampValue(Object value) {
        if (value == null) {
            return null;
        }
        if (value instanceof LocalDateTime) {
            return (LocalDateTime) value;
        }

        String strValue = value.toString().trim();

        String[] patterns = {
                "yyyy-MM-dd HH:mm:ss.SSS",
                "yyyy-MM-dd HH:mm:ss",
                "yyyy-MM-dd'T'HH:mm:ss.SSS",
                "yyyy-MM-dd'T'HH:mm:ss",
                "yyyy-MM-dd HH:mm:ss.SSSSSS",
                "yyyy-MM-dd HH:mm:ss.SSSSS",
                "yyyy-MM-dd HH:mm:ss.S",
                "yyyy-MM-dd HH:mm:ss.SS",
                "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS",
                "yyyy-MM-dd",
                "yyyy/MM/dd HH:mm:ss",
                "yyyy/MM/dd HH:mm:ss.SSS"
        };

        for (String pattern : patterns) {
            try {
                return LocalDateTime.parse(strValue, java.time.format.DateTimeFormatter.ofPattern(pattern));
            } catch (Exception ignored) {
            }
        }

        try {
            return LocalDateTime.parse(strValue);
        } catch (Exception e) {
            log.warn("无法解析时间字符串: {}", strValue);
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    private String[] getStringArray(Object value) {
        if (value == null) {
            return new String[0];
        }
        if (value instanceof String[]) {
            return (String[]) value;
        }
        if (value instanceof Object[]) {
            Object[] arr = (Object[]) value;
            String[] result = new String[arr.length];
            for (int i = 0; i < arr.length; i++) {
                result[i] = arr[i] != null ? arr[i].toString() : null;
            }
            return result;
        }
        String str = value.toString();
        if (str.startsWith("[") && str.endsWith("]")) {
            str = str.substring(1, str.length() - 1).trim();
            if (str.isEmpty()) {
                return new String[0];
            }
            String[] parts = str.split(",");
            String[] result = new String[parts.length];
            for (int i = 0; i < parts.length; i++) {
                String part = parts[i].trim();
                if (part.startsWith("\"") && part.endsWith("\"")) {
                    part = part.substring(1, part.length() - 1);
                }
                result[i] = part;
            }
            return result;
        }
        if (str.startsWith("{") && str.endsWith("}")) {
            str = str.substring(1, str.length() - 1);
            return str.split(",");
        }
        return new String[]{str};
    }

    @SuppressWarnings("unchecked")
    private Integer[] getIntegerArray(Object value) {
        if (value == null) {
            return new Integer[0];
        }
        String[] strArray = getStringArray(value);
        Integer[] result = new Integer[strArray.length];
        for (int i = 0; i < strArray.length; i++) {
            try {
                result[i] = Integer.parseInt(strArray[i]);
            } catch (NumberFormatException e) {
                result[i] = null;
            }
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    private byte[][] getByteArrayArray(Object value) {
        if (value == null) {
            return new byte[0][];
        }
        if (value instanceof byte[][]) {
            return (byte[][]) value;
        }
        if (value instanceof Object[]) {
            Object[] arr = (Object[]) value;
            byte[][] result = new byte[arr.length][];
            for (int i = 0; i < arr.length; i++) {
                if (arr[i] instanceof byte[]) {
                    result[i] = (byte[]) arr[i];
                } else {
                    result[i] = arr[i] != null ? arr[i].toString().getBytes() : null;
                }
            }
            return result;
        }
        return new byte[0][];
    }

    private String convertAlarmLevel(Integer eventLevel) {
        if (eventLevel == null) return "未知";
        switch (eventLevel) {
            case 0: return "安全(无威胁)";
            case 1: return "低危";
            case 2: return "中危";
            case 3: return "高危";
            case 4: return "超危";
            default: return "未知";
        }
    }

    private String buildComment(Map<String, Object> row) {
        String victimIpsStr;
        if (row.containsKey("victim_ip")) {
            victimIpsStr = String.join(",", getStringArray(row.get("victim_ip")));
        } else {
            victimIpsStr = "未知";
        }
        String alarmName = "";
        if (row.containsKey("alarm_name")) {
            alarmName = getStringValue(row.get("alarm_name"));
        }
        String AttackIps = "";
        if (row.containsKey("attack_ip")) {
            AttackIps = String.join(",", getStringArray(row.get("attack_ip")));
        }
        return String.format(
                "24小时内，检测到%s上产生%s告警：\n告警名称：%s\n攻击IP：%s\n攻击结果：%d",
                victimIpsStr,
                convertAlarmLevel(getIntegerValue(row.get("alarm_level"))),
                alarmName,
                AttackIps,
                determineAttackResult(row)
        );
    }

    private String convertAttackIps(String[] attackIps) {
        if (attackIps == null || attackIps.length == 0) {
            return null;
        }
        return String.join(",", attackIps);
    }

    private Integer determineAttackResult(Map<String, Object> row) {
        if (row.containsKey("attack_result")) {
            return getIntegerValue(row.get("attack_result"));
        } else {
            return -1;
        }
    }
}
