package com.common.util;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.common.entity.SyslogMessage;
import com.common.entity.RFC3164Message;
import com.common.entity.RFC5424Message;
import com.influx.SyslogToInfluxApp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.Locale;

public class SyslogParser {
    private static final Logger logger = LoggerFactory.getLogger(SyslogToInfluxApp.class);
    // RFC 5424 正则表达式
    private static final Pattern RFC5424_PATTERN = Pattern.compile(
            "^<(?<pri>\\d{1,3})>(?<version>\\d+) " +
                    "(?<timestamp>\\S+) " +
                    "(?<host>\\S+) " +
                    "(?<app>\\S+) " +
                    "(?<pid>\\S+) " +
                    "(?<msgid>\\S+) " +
                    "(?<sd>(?:-|\\[.*\\]))" +
                    "(?: (?<message>.+))?$"
    );

    // RFC 3164 正则表达式
    private static final Pattern RFC3164_PATTERN = Pattern.compile(
            "^<(?<pri>\\d{1,3})>" +
                    "(?<timestamp>[A-Z][a-z]{2}\\s+\\d{1,2}\\s+\\d{2}:\\d{2}:\\d{2}) " +
                    "(?<host>\\S+) " +
                    "(?<content>.+)$"
    );

    // RFC 3164 时间戳格式
    private static final DateTimeFormatter RFC3164_FORMATTER =
            DateTimeFormatter.ofPattern("MMM dd HH:mm:ss");

    /**
     * 解析 Syslog 消息，自动检测格式
     */
    public static SyslogMessage parse(String logLine) {
        if (logLine == null || logLine.trim().isEmpty()) {
            throw new IllegalArgumentException("Log line cannot be null or empty");
        }
        // 尝试解析为 RFC 5424 格式
        try {
            RFC5424Message msg5424 = parseRFC5424(logLine);
            if (msg5424 != null) {
                return msg5424;
            }
        } catch (Exception e) {
            // 继续尝试 RFC 3164
        }

        // 尝试解析为 RFC 3164 格式
        try {
            RFC3164Message msg3164 = parseRFC3164(logLine);
            if (msg3164 != null) {
                return msg3164;
            }
        } catch (Exception e) {
            // 解析失败
        }
        // 解析非标数据格式，提取字符【{】自后的内容
        try {
            String  content   = extractJsonStringNew(logLine);
            RFC5424Message msgClass  =new RFC5424Message();
            if (content != null) {
                msgClass.setMessage(content.toString());
                return msgClass;
            }
        } catch (Exception e) {
            // 解析失败
        }
        throw new IllegalArgumentException("Unable to parse syslog message: " + logLine);
    }

    /**
     * 解析 RFC 5424 格式
     */
    public static RFC5424Message parseRFC5424(String logLine) {
        Matcher matcher = RFC5424_PATTERN.matcher(logLine);
        if (!matcher.find()) {
            return null;
        }
        RFC5424Message message = new RFC5424Message();
        // 解析优先级
        int pri = Integer.parseInt(matcher.group("pri"));
        message.setPriority(pri);

        // 解析版本
        message.setVersion(Integer.parseInt(matcher.group("version")));

        // 解析时间戳 (RFC 3339 格式)
        String timestampStr = matcher.group("timestamp");
        try {
            message.setTimestamp(OffsetDateTime.parse(timestampStr));
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("Invalid RFC5424 timestamp: " + timestampStr, e);
        }
        // 解析其他字段
        message.setHostname(matcher.group("host"));
        message.setAppName(matcher.group("app"));
        message.setProcId(matcher.group("pid"));
        message.setMsgId(matcher.group("msgid"));

        // 解析结构化数据
        String sd = matcher.group("sd");
        if (!"-".equals(sd)) {
            message.setStructuredData(parseStructuredData(sd));
        }
        // 解析消息内容
        String msg = matcher.group("message");
        if (msg != null) {
            message.setMessage(msg.trim());
        }
        return message;
    }

    /**
     * 解析 RFC 3164 格式
     */
    public static RFC3164Message parseRFC3164(String logLine) {
        Matcher matcher = RFC3164_PATTERN.matcher(logLine);
        if (!matcher.find()) {
            return null;
        }

        RFC3164Message message = new RFC3164Message();

        // 解析优先级
        int pri = Integer.parseInt(matcher.group("pri"));
        message.setPriority(pri);

        // 解析时间戳 (需要特殊处理，因为没有年份)
        String timestampStr = matcher.group("timestamp");
        message.setTimestamp(parseRFC3164Timestamp(timestampStr));

        // 解析主机名
        message.setHostname(matcher.group("host"));

        // 解析内容和标签
        String content = matcher.group("content");
        parseRFC3164Content(content, message);

        return message;
    }

    /**
     * 解析 RFC 3164 时间戳
     */
    private static OffsetDateTime parseRFC3164Timestamp(String timestampStr) {
        try {
            // 添加当前年份，因为 RFC3164 时间戳不包含年份
            String currentYear = String.valueOf(java.time.Year.now().getValue());
            String fullTimestamp = currentYear + " " + timestampStr;

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MMM dd HH:mm:ss", Locale.US);
            LocalDateTime localDateTime = LocalDateTime.parse(fullTimestamp, formatter);
           // DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MMM dd HH:mm:ss", Locale.US);

            // 假设为系统默认时区
            return localDateTime.atOffset(ZoneOffset.systemDefault().getRules().getOffset(localDateTime));
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("Invalid RFC3164 timestamp: " + timestampStr, e);
        }
    }

    /**
     * 解析 RFC 3164 内容部分
     */
    private static void parseRFC3164Content(String content, RFC3164Message message) {
        // 尝试匹配标签格式: app[pid]:
        Pattern tagPattern = Pattern.compile("^(?<tag>\\S+?)(?:\\[(?<pid>\\d+)\\])?:\\s*(?<message>.*)$");
        Matcher tagMatcher = tagPattern.matcher(content);

        if (tagMatcher.find()) {
            message.setTag(tagMatcher.group("tag"));
            String pid = tagMatcher.group("pid");
            if (pid != null) {
                message.setProcId(pid);
            }
            message.setMessage(tagMatcher.group("message").trim());
        } else {
            // 如果没有标签格式，整个内容作为消息
            message.setTag("");
            message.setMessage(content.trim());
        }

        // 对于 RFC3164，appName 通常与 tag 相同
        message.setAppName(message.getTag());
    }

    /**
     * 解析结构化数据
     */
    private static Map<String, Map<String, String>> parseStructuredData(String sd) {
        Map<String, Map<String, String>> structuredData = new HashMap<>();

        // 简单的结构化数据解析，实际应用可能需要更复杂的解析
        Pattern sdPattern = Pattern.compile("\\[(?<id>[^\\]]+)\\]");
        Pattern paramPattern = Pattern.compile("(?<key>[^=\\s]+)=\"(?<value>[^\"]*)\"");

        Matcher sdMatcher = sdPattern.matcher(sd);
        while (sdMatcher.find()) {
            String sdElement = sdMatcher.group("id");
            Map<String, String> params = new HashMap<>();

            Matcher paramMatcher = paramPattern.matcher(sdElement);
            while (paramMatcher.find()) {
                params.put(paramMatcher.group("key"), paramMatcher.group("value"));
            }
            // 使用第一个参数作为键，或者生成一个键
            String key = params.containsKey("sdId") ? params.get("sdId") :
                    "element" + structuredData.size();
            structuredData.put(key, params);
        }
        return structuredData;
    }


    /**
     * 提取 JSON 字符串（不解析）
     */
    public static Optional<String> extractJsonString(String syslogMessage) {
        try {
            if (syslogMessage == null) return Optional.empty();

            int jsonStart = syslogMessage.indexOf('{');
            if (jsonStart == -1) return Optional.empty();
            return Optional.of(syslogMessage.substring(jsonStart));
        } catch (Exception e) {
            return Optional.empty();
        }
    }

    /**
     * 提取 JSON 字符串（不解析）
     */
    public static String  extractJsonStringNew (String syslogMessage) {
        try {
            if (syslogMessage == null) return "";

            int jsonStart = syslogMessage.indexOf('{');
            if (jsonStart == -1) return "";

            return  syslogMessage.substring(jsonStart);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 截取字符串中第一个 ']' 之后的所有内容
     *
     * @param text 原始字符串
     * @return 第一个 ']' 之后的内容，如果没有 ']' 则返回空字符串
     */
    public static String substringAfterFirstCloseBracket(String text) {
        if (text == null) {
            return "";
        }

        int closeBracketIndex = text.indexOf(']');

        if (closeBracketIndex == -1) {
            return ""; // 没有找到 ']'，返回空字符串
        }

        // 返回 ']' 之后的内容（+1 是为了跳过 ']' 本身）
        return text.substring(closeBracketIndex + 1);
    }

    /**
     * 截取字符串中第一个指定字符之前的所有内容
     *
     * @param text 原始字符串
     * @param delimiterChar 分隔字符
     * @return 分隔字符之前的内容
     */
    public static String substringBeforeFirstChar(String text, char delimiterChar) {
        if (text == null) {
            return "";
        }

        int delimiterIndex = text.indexOf(delimiterChar);

        if (delimiterIndex == -1) {
            return text;
        }
        return text.substring(0, delimiterIndex+1);
    }

    /**
     * 从文本中提取第一个 [] 包裹的键值对字符串并转换为 Map
     *
     * @param text 包含键值对的原始文本
     * @return 包含键值对的 Map
     * @throws IllegalArgumentException 如果格式不正确
     */
    public static Map<String, String> parseKeyValuePairs(String text) {
        if (text == null || text.trim().isEmpty()) {
            throw new IllegalArgumentException("Input text cannot be null or empty");
        }

        // 查找第一个 [ 和对应的 ]
        int start = text.indexOf('[');
        int end = text.indexOf(']', start + 1);

        if (start == -1 || end == -1) {
            throw new IllegalArgumentException("No valid [] pair found in text");
        }

        // 提取 [] 内的内容
        String content = text.substring(start + 1, end).trim();
        if (content.isEmpty()) {
            return new HashMap<>(); // 返回空Map
        }

        // 分割键值对
        String[] pairs = content.split("\\s+");
        Map<String, String> result = new HashMap<>();

        for (String pair : pairs) {
            // 分割键和值
            int equalSign = pair.indexOf('=');
            if (equalSign == -1) {
                throw new IllegalArgumentException("Invalid key-value pair format: " + pair);
            }

            String key = pair.substring(0, equalSign).trim();
            String value = pair.substring(equalSign + 1).trim();

            if (key.isEmpty()) {
                throw new IllegalArgumentException("Key cannot be empty in pair: " + pair);
            }

            result.put(key, value);
        }

        return result;
    }
}

