package org.example.Entity.System;

import org.example.Utils.NativeExtensionUtils;
import org.example.Utils.PublicUtil;
import org.example.Utils.WebConfigUtil_web;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.example.Utils.NativeExtensionUtils.dmToBoolean;
import static org.example.Utils.NativeExtensionUtils.toBoolean;

public class FieldModel {
    private NamedParameterJdbcTemplate jdbcTemplate;

    // 数据库操作器（通过构造注入）
    public void setJdbcTemplate(NamedParameterJdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public boolean IsNullAble;
    public Class<?> ctype;
    public int dbType;

    public String databaseType;

    public  String getDatabaseType(){
        return databaseType = WebConfigUtil_web.get("custom.database.type");
    }

    // 获取数据库参数对象
    public SqlParameter getPm() {
        if (pmFiledValue == null) {
            return new SqlParameter("@" + FiledName, Types.VARCHAR);
        }
        // 根据实际类型设置SQL类型
        int sqlType = getSqlTypeByClass(ctype);
        return new SqlParameter("@" + FiledName, sqlType);
    }

    public String getPmName() {
        return String.format("@%s", FiledName);
    }

    public String FiledName;
    public String FiledLabel;
    public boolean hasSpecVal = false;
    private Object _filedvalue;

    private static final String[] KEY_WORDS = {"'", "<"};
    private static final Pattern REGEX_SQL_KEYWORD = Pattern.compile(
            "\\b(SELECT|UPDATE|DELETE|INSERT|FROM|WHERE|AND|OR|NOT|IN|LIKE|AS|CREATE|ALTER|DROP|TRUNCATE|CASCADE|COALESCE|IF|EXISTS|GRANT|REVOKE|LOCK|UNION|ALL|ANY|SOME|INTERSECT|EXCEPT)\\b",
            Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE
    );

    private static boolean hasKeyWords(String input) {
        if (input == null) return false;
        for (String word : KEY_WORDS) {
            if (input.contains(word)) return true;
        }
        return REGEX_SQL_KEYWORD.matcher(input).find() || input.startsWith("data:");
    }

    public boolean TrimSpec;
    public int FieldLength;

    public boolean validLength(int[] valueLen) {
        valueLen[0] = 0;
        if (ctype == String.class) {
            String value = (getFiledValue() + "").trim(); // 移除trim()方法的参数
            // 如果需要根据trimSpec处理不同的修剪逻辑，可以分情况处理
            if (TrimSpec) {
                value = value.replace("'", ""); // 移除单引号
            } else {
                value = value.trim(); // 修剪空格
            }
            valueLen[0] = getStringLen(value);
            return valueLen[0] <= FieldLength;
        }
        return true;
    }

    public String ValidMsg;

    public static int getStringLen(String text) {
        if (text == null) return 0;
        byte[] bytes = text.getBytes(StandardCharsets.US_ASCII);
        int length = 0;
        for (byte b : bytes) {
            // ASCII码63对应'?'，表示非ASCII字符
            length += (b == 63) ? 2 : 1;
        }
        return length;
    }

    public Object SqlFieldVal;
    public Object pmFiledValue;

    // 设置字段值（核心逻辑）
    public void setFiledValue(Object value) {
        _filedvalue = value;

//        System.out.println("字段名：" + FiledName + "，ctype类型：" + (ctype != null ? ctype.getName() : "null"));

        // 检查是否为空
        if (isStringNullOrEmpty(objectToString(_filedvalue))) {
            _filedvalue = PublicUtil.GetSqlDefaultValByType(ctype, IsNullAble);
            pmFiledValue = _filedvalue;
            SqlFieldVal = _filedvalue;
            return;
        }

        // 处理big int类型的特殊情况
        String filedStr = objectToString(_filedvalue);
        if (filedStr.startsWith("0E-")) {
            _filedvalue = 0;
            pmFiledValue = _filedvalue;
            SqlFieldVal = _filedvalue;
            return;
        }

        // 处理列表类型
        if (_filedvalue instanceof List<?>) {
            _filedvalue = sJoin((List<?>) _filedvalue);
        }

        // 处理字符串修剪
        String tempValue = objectToString(_filedvalue).trim();
        _filedvalue = tempValue;

        if (TrimSpec && tempValue.startsWith("'") && tempValue.endsWith("'")) {
            _filedvalue = tempValue.substring(1, tempValue.length() - 1);
        }

        if (!isStringNullOrEmpty(objectToString(_filedvalue))) {
            // 处理数值类型
            if (ctype == int.class || ctype == Integer.class ||
                    ctype == float.class || ctype == Float.class ||
                    ctype == double.class || ctype == Double.class ||
                    ctype == BigDecimal.class ||
                    ctype == long.class || ctype == Long.class)
            {
                String valueStr = objectToString(_filedvalue).trim();
                if (valueStr.indexOf('E') > -1 || valueStr.indexOf('e') > -1) {
                    Pattern pattern = Pattern.compile("[^\\d\\.\\-Ee]");
                    Matcher matcher = pattern.matcher(valueStr);
                    if (!matcher.find()) {
                        try {
                            _filedvalue = new BigDecimal(valueStr);
                        } catch (NumberFormatException e) {
                            handleInvalidNumberFormat(valueStr);
                        }
                    } else {
                        handleInvalidNumberFormat(valueStr);
                    }
                } else {
                    Pattern pattern = Pattern.compile("[^\\d\\.\\-\\,]");
                    Matcher matcher = pattern.matcher(valueStr);
                    if (matcher.find() || "-".equals(valueStr) || ".".equals(valueStr)) {
                        if ("true".equalsIgnoreCase(valueStr) || "false".equalsIgnoreCase(valueStr)) {
                            _filedvalue = "true".equalsIgnoreCase(valueStr) ? 1 : 0;
                        } else {
                            ValidMsg = String.format("字段%s输入字符串类型不正确，输入值为%s，应该为%s类型！",
                                    FiledName, _filedvalue, ctype.getName());
                            _filedvalue = 0;
                        }
                    } else {
                        try {
                            _filedvalue = new BigDecimal(valueStr.replace(",", ""));
                        } catch (NumberFormatException e) {
                            handleInvalidNumberFormat(valueStr);
                        }
                    }
                }
            }
            // 处理日期类型
            else if (ctype == Date.class && !(value instanceof Date)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                try {
                    Date dvalue = sdf.parse(objectToString(value));
                    _filedvalue = sdf.format(dvalue);
                } catch (ParseException e) {
                    ValidMsg = String.format("字段%s输入时间类型值格式不正确，输入值为%s，应该为标准时间类型！",
                            FiledName, _filedvalue);
                }
            }
            // 处理布尔类型
            else if (ctype == boolean.class || ctype == Boolean.class) {
              if (getDatabaseType().equals("dm"))  _filedvalue = dmToBoolean(Objects.toString(_filedvalue));
                  else _filedvalue = toBoolean(_filedvalue);
            }
            // 处理字符串类型
            else if (ctype == String.class) {
                String valueStr = objectToString(_filedvalue);
                int vLen = valueStr.length();

                if (hasKeyWords(valueStr)) {
                    Pattern pattern = Pattern.compile("\"");
                    Matcher matcher = pattern.matcher(valueStr);
                    vLen += matcher.groupCount();
                }
                if (FieldLength > 0 && vLen > FieldLength) {
                    int subLength = Math.min(FieldLength, valueStr.length());
                    _filedvalue = valueStr.substring(0, subLength);
                    ValidMsg = String.format("字段%s输入字符串长度过长，应该在%s个字符范围内！现有长度%s！",
                            FiledName, FieldLength, vLen);
                }
            }

            pmFiledValue = _filedvalue;
            SqlFieldVal = _filedvalue;
//            if (hasKeyWords(objectToString(_filedvalue))) {
//                hasSpecVal = true;
//                _filedvalue = "";
//            }

//            SqlFieldVal = _filedvalue;

            // 处理数据库类型
            if (dbType == 231) { // nvarchar
                SqlFieldVal = String.format("N'%s'", escapeSql(objectToString(SqlFieldVal)));
            } else {
                SqlFieldVal = String.format("'%s'", escapeSql(objectToString(SqlFieldVal)));
            }
        } else {
            _filedvalue = PublicUtil.GetSqlDefaultValByType(ctype, IsNullAble);
            pmFiledValue = _filedvalue;
            SqlFieldVal = _filedvalue;
        }
    }

    // 辅助方法：处理无效的数字格式
    private void handleInvalidNumberFormat(String valueStr) {
        if ("true".equalsIgnoreCase(valueStr) || "false".equalsIgnoreCase(valueStr)) {
            _filedvalue = "true".equalsIgnoreCase(valueStr) ? 1 : 0;
        } else {
            ValidMsg = String.format("字段%s输入字符串类型不正确，输入值为%s，应该为%s类型！",
                    FiledName, _filedvalue, ctype.getName());
            _filedvalue = 0;
        }
    }

    // 辅助方法：SQL转义
    private String escapeSql(String str) {
        if (str == null) {
            return "";
        }
        return str.replace("'", "''");
    }

    // 辅助方法：将对象转换为字符串
    private String objectToString(Object obj) {
        if (obj == null) {
            return "";
        }
        return obj.toString();
    }

    // 辅助方法：检查字符串是否为空
    private boolean isStringNullOrEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }

    // 辅助方法：List转换为字符串
    private String sJoin(List<?> list) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            if (i > 0) {
                sb.append(",");
            }
            sb.append(objectToString(list.get(i)));
        }
        return sb.toString();
    }

    public Object getFiledValue() {
        return _filedvalue;
    }

    // 辅助方法：根据Java类型获取SQL类型
    private int getSqlTypeByClass(Class<?> type) {
        if (type == Integer.class) return Types.INTEGER;
        if (type == Long.class) return Types.BIGINT;
        if (type == String.class) return Types.VARCHAR;
        if (type == Date.class) return Types.DATE;
        if (type == Timestamp.class) return Types.TIMESTAMP;
        if (type == Boolean.class) return Types.BOOLEAN;
        if (type == BigDecimal.class) return Types.DECIMAL;
        return Types.VARCHAR;
    }
}