package vip.xiaonuo.coldchain.core.handler.abs;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 自定义 MyBatis 类型处理器，用于处理 List<T> 类型的字段，存储为字符串（JSON 格式）。
 * @param <T> 泛型类型
 */
@Slf4j
@MappedJdbcTypes({JdbcType.VARCHAR})
@MappedTypes({List.class})
public abstract class ListTypeHandler<T> extends BaseTypeHandler<List<T>> {
    // 静态实例化 ObjectMapper，避免每次调用都创建新的实例
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public ListTypeHandler() {
    }

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<T> ts, JdbcType jdbcType) throws SQLException {
        // 将 List<T> 转换为 JSON 字符串存储
        String content = CollectionUtil.isEmpty(ts) ? null : this.toJSONString(ts);
        preparedStatement.setString(i, content);
    }

    @Override
    public List<T> getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        try {
            return this.getListByJsonArrayString(resultSet.getString(columnName));
        } catch (JsonProcessingException e) {
            log.error("从 ResultSet 获取数据并转换为 List<T> 时出错，column: {}", columnName, e);
            throw new SQLException("JSON 解析错误", e);
        }
    }

    @Override
    public List<T> getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        try {
            return this.getListByJsonArrayString(resultSet.getString(columnIndex));
        } catch (JsonProcessingException e) {
            log.error("从 ResultSet 获取数据并转换为 List<T> 时出错，columnIndex: {}", columnIndex, e);
            throw new SQLException("JSON 解析错误", e);
        }
    }

    @Override
    public List<T> getNullableResult(CallableStatement callableStatement, int parameterIndex) throws SQLException {
        try {
            return this.getListByJsonArrayString(callableStatement.getString(parameterIndex));
        } catch (JsonProcessingException e) {
            log.error("从 CallableStatement 获取数据并转换为 List<T> 时出错，parameterIndex: {}", parameterIndex, e);
            throw new SQLException("JSON 解析错误", e);
        }
    }

    /**
     * 将 JSON 字符串转换为 List<T>。
     * @param content JSON 字符串
     * @return List<T> 对象
     * @throws JsonProcessingException 如果 JSON 解析失败
     */
    public List<T> getListByJsonArrayString(String content) throws JsonProcessingException {
        if (StringUtils.isEmpty(content)) {
            return new ArrayList<>();
        } else {
            try {
                return objectMapper.readValue(content, this.specificType());
            } catch (JsonProcessingException e) {
                log.error("JSON 解析失败，无法将字符串转换为 List<T>，content: {}", content, e);
                throw e;
            }
        }
    }

    /**
     * 默认的 TypeReference 提供了 List<T> 的类型信息。
     * 子类可以覆盖此方法以提供更具体的类型信息。
     * @return List<T> 的 TypeReference 类型信息
     */
    public abstract TypeReference<List<T>> specificType();

    /**
     * 将对象转换为 JSON 字符串。
     * @param obj 对象
     * @return JSON 字符串
     */
    public String toJSONString(Object obj) {
        try {
            return obj == null ? null : JSONUtil.toJsonStr(obj);
        } catch (Exception e) {
            log.error("对象转换为 JSON 字符串时失败，obj: {}", obj, e);
            throw new RuntimeException("对象转换为 JSON 失败", e);
        }
    }
}
