package org.example.Utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 配置工具类，读取并解析数据库连接配置
 * 功能对应C#的ConfigUtil
 */
@Component
public class ConfigUtil {
    private static final Logger log = LoggerFactory.getLogger(ConfigUtil.class);


    // 静态字段存储配置值
    private static String defaultConnectionString;

    // 非静态setter方法，用@Value注入值后赋值给静态字段
    @Value("${spring.datasource.url:}")
    public void setDefaultConnectionString(String url) {
        log.debug("Default datasource URL configured: {}", url != null && !url.isBlank());
        // 将注入的非静态值赋值给静态字段
        ConfigUtil.defaultConnectionString = url;
    }
    // 静态方法供外部访问
    public static String getDefaultConnectionString() {
        return defaultConnectionString;
    }

    // 静态字段存储默认Provider
    private static String defaultProviderName;
    private static String defaultProviderType;

    // 非静态setter，用于Spring注入并给静态字段赋值
    @Value("${spring.datasource.driver-class-name}")
    public void setDefaultProviderType(String driverClassType) {
        ConfigUtil.defaultProviderType = driverClassType;
    }

    // 非静态setter，用于Spring注入并给静态字段赋值
    @Value("${custom.database.type}")
    public void setDefaultProviderName(String driverClassName) {
        ConfigUtil.defaultProviderName = driverClassName;
    }

    // 从配置文件注入数据库超时时间
    @Value("${dbTimeout:120}")
    private String dbTimeout;


    // 全局设置的驱动类名（可动态修改）
    private static String seteedProvider;

    // 连接字符串解析后的键值对缓存
    private static Map<String, String> connectionKeyVal;

    // 数据库超时时间缓存
    private static int timeOut = 0;
    private static String seteedconstr;

    // 2. 静态实例（用于静态方法访问非静态字段）
    private static ConfigUtil instance;

    // 初始化静态实例（在Spring注入完成后执行）
    @PostConstruct
    public void init() {
        instance = this; // 将当前实例赋值给静态变量
    }

    /**
     * 设置全局连接字符串
     */
    public static void setConStr(String constr) {
        seteedconstr = constr;
        connectionKeyVal = null; // 重置缓存
    }

    /**
     * 设置全局连接字符串和驱动类名
     */
    public static void setConStr(String constr, String provider) {
        seteedconstr = constr;
        seteedProvider = provider;
        connectionKeyVal = null; // 重置缓存
    }

    /**
     * 获取当前有效的连接字符串
     */
    public static String getConnectionString() {
        if (seteedconstr != null && !seteedconstr.isEmpty()) {
            return seteedconstr;
        }
        return instance.defaultConnectionString;
    }

    /**
     * 获取当前有效的驱动类名
     */
    public static String getProviderName() {
        if (seteedProvider != null && !seteedProvider.isEmpty()) {
            return seteedProvider;
        }
        return defaultProviderName;
    }

    public static String getProviderType() {
        if (seteedProvider != null && !seteedProvider.isEmpty()) {
            return seteedProvider;
        }
        return defaultProviderType;
    }

    /**
     * 获取数据库操作超时时间（秒）
     */
    public int getTimeOut() {
        if (timeOut <= 0) {
            // 移除非数字字符后转换为整数
            String numericTimeout = Pattern.compile("\\D").matcher(dbTimeout).replaceAll("");
            timeOut = NativeExtensionUtils.parseInt(numericTimeout, 120);
        }
        return timeOut;
    }

    /**
     * 获取连接字符串解析后的键值对（小写键）
     */
    public static Map<String, String> getConnectionKeyVal() {
        if (connectionKeyVal == null) {
            String conStr = getConnectionString();
            if (conStr == null || conStr.isEmpty()) {
                connectionKeyVal = new HashMap<>();
                return connectionKeyVal;
            }
            connectionKeyVal = toConDict(conStr);
        }
        return connectionKeyVal;
    }

    /**

     将连接字符串解析为键值对（键转为小写）
     优先使用；分割解析，若解析后 user 为空，则尝试用？和 & 分割解析
     */
    public static Map<String, String> toConDict (String conStr) {
        Map<String, String> result = new HashMap<>();
        if (conStr == null || conStr.isEmpty ()) {
            return result;
        }
// 1. 优先使用；分割解析
        Map<String, String> semicolonResult = parseWithSemicolon (conStr);
        String userValue = semicolonResult.getOrDefault ("user", "").trim ();
        if (!userValue.isEmpty ()) {
            return semicolonResult;
        }
// 2. 若；分割解析的 user 为空，则使用？和 & 分割解析
        return parseWithAmpersand (conStr);
    }

    /**

     用；分割连接字符串解析键值对
     */
    private static Map<String, String> parseWithSemicolon (String conStr) {
        Map<String, String> result = new HashMap<>();
        String [] parts = conStr.split (";");
        for (String part : parts) {
            part = part.trim ();
            if (part.isEmpty ()) {
                continue;
            }
            int eqIndex = part.indexOf ('=');
            if (eqIndex > 0) {
                String key = part.substring (0, eqIndex).trim ().toLowerCase ();
                String value = part.substring (eqIndex + 1).trim ();
                result.put (key, value);
            }
        }
        return result;
    }

    /**

     用？和 & 分割连接字符串解析键值对（URL 参数格式）
     */
    private static Map<String, String> parseWithAmpersand (String conStr) {
        Map<String, String> result = new HashMap<>();
// 分割出参数部分（去掉？之前的内容）
        String [] urlParts = conStr.split ("\\?", 2); // 最多分割成两部分
        String paramPart = urlParts.length > 1 ? urlParts [1] : conStr;
// 用 & 分割参数
        String [] params = paramPart.split ("&");
        for (String param : params) {
            param = param.trim ();
            if (param.isEmpty ()) {
                continue;
            }
            int eqIndex = param.indexOf ('=');
            if (eqIndex > 0) {
                String key = param.substring (0, eqIndex).trim ().toLowerCase ();
                String value = param.substring (eqIndex + 1).trim ();
                result.put (key, value);
            }
        }
        return result;
    }
}
