package com.infoepoch.pms.agent.platform.chat.adapter.out.persistence;

import com.infoepoch.pms.agent.common.utils.LogHelper;
import com.infoepoch.pms.agent.common.utils.OracleUtils;
import com.infoepoch.pms.agent.platform.chat.domain.GraphCheckPoint;
import com.infoepoch.pms.agent.platform.chat.domain.irepository.GraphCheckPointCriteria;
import com.infoepoch.pms.agent.platform.chat.domain.irepository.IGraphCheckPointRepository;
import com.infoepoch.pms.agent.platform.shared.exception.ValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author jiangyz
 * @date 2026/4/18 10:34
 * 检查点仓储实现
 */
@Repository
public class GraphCheckPointRepository implements IGraphCheckPointRepository {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 新增
     */
    @Override
    public boolean insert(GraphCheckPoint entity) {
        String sql = "INSERT INTO AI_GRAPHCHECKPOINT(CHECKPOINT_ID, PARENT_CHECKPOINT_ID, THREAD_ID, NODE_ID, NEXT_NODE_ID, STATE_DATA, STATE_CONTENT_TYPE, SAVED_AT) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
        int result;
        try {
            result = jdbcTemplate.update(sql, entity.getCheckPointId(), entity.getParentCheckPointId(), entity.getThreadId(), entity.getNodeId(), entity.getNextNodeId(), entity.getStateData(), entity.getStateContentType(), entity.getSavedAt() != null ? Timestamp.valueOf(entity.getSavedAt()) : null);
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            throw new ValidationException("新增 检查点 数据 失败。");
        }
        return result > 0;
    }

    /**
     * 更新
     */
    @Override
    public boolean update(GraphCheckPoint entity) {
        String sql = "UPDATE AI_GRAPHCHECKPOINT SET PARENT_CHECKPOINT_ID = ?, THREAD_ID = ?, NODE_ID = ?, NEXT_NODE_ID = ?, STATE_DATA = ?, STATE_CONTENT_TYPE = ?, SAVED_AT = ? WHERE CHECKPOINT_ID = ?";
        int result;
        try {
            result = jdbcTemplate.update(sql, entity.getParentCheckPointId(), entity.getThreadId(), entity.getNodeId(), entity.getNextNodeId(), entity.getStateData(), entity.getStateContentType(), entity.getSavedAt() != null ? Timestamp.valueOf(entity.getSavedAt()) : null, entity.getCheckPointId());
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            throw new ValidationException("更新 检查点 数据 失败。");
        }
        return result >= 0;
    }

    @Override
    public boolean replaceCheckpoint(String previousCheckPointId, GraphCheckPoint entity) {
        String sql = "UPDATE AI_GRAPHCHECKPOINT SET CHECKPOINT_ID = ?, PARENT_CHECKPOINT_ID = ?, THREAD_ID = ?, NODE_ID = ?, NEXT_NODE_ID = ?, STATE_DATA = ?, STATE_CONTENT_TYPE = ?, SAVED_AT = ? WHERE CHECKPOINT_ID = ?";
        int result;
        try {
            result = jdbcTemplate.update(sql,
                    entity.getCheckPointId(),
                    entity.getParentCheckPointId(),
                    entity.getThreadId(),
                    entity.getNodeId(),
                    entity.getNextNodeId(),
                    entity.getStateData(),
                    entity.getStateContentType(),
                    entity.getSavedAt() != null ? Timestamp.valueOf(entity.getSavedAt()) : null,
                    previousCheckPointId);
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            throw new ValidationException("替换 检查点 数据 失败。");
        }
        return result > 0;
    }

    /**
     * 批量新增
     */
    public int[] batchInsert(List<GraphCheckPoint> list) {
        String sql = "INSERT INTO AI_GRAPHCHECKPOINT(CHECKPOINT_ID, PARENT_CHECKPOINT_ID, THREAD_ID, NODE_ID, NEXT_NODE_ID, STATE_DATA, STATE_CONTENT_TYPE, SAVED_AT) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
        int[] result = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                int j = 0;
                GraphCheckPoint item = list.get(i);
                ps.setString(++j, item.getCheckPointId());
                ps.setString(++j, item.getParentCheckPointId());
                ps.setString(++j, item.getThreadId());
                ps.setString(++j, item.getNodeId());
                ps.setString(++j, item.getNextNodeId());
                ps.setString(++j, item.getStateData());
                ps.setString(++j, item.getStateContentType());
                ps.setTimestamp(++j, item.getSavedAt() != null ? Timestamp.valueOf(item.getSavedAt()) : null);
            }

            @Override
            public int getBatchSize() {
                return list.size();
            }
        });
        return result;
    }

    /**
     * 批量更新
     */
    public int[] batchUpdate(List<GraphCheckPoint> list) {
        String sql = "UPDATE AI_GRAPHCHECKPOINT SET PARENT_CHECKPOINT_ID = ?, THREAD_ID = ?, NODE_ID = ?, NEXT_NODE_ID = ?, STATE_DATA = ?, STATE_CONTENT_TYPE = ?, SAVED_AT = ? WHERE CHECKPOINT_ID = ? ";
        int[] result = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                int j = 0;
                GraphCheckPoint item = list.get(i);
                ps.setString(++j, item.getParentCheckPointId());
                ps.setString(++j, item.getThreadId());
                ps.setString(++j, item.getNodeId());
                ps.setString(++j, item.getNextNodeId());
                ps.setString(++j, item.getStateData());
                ps.setString(++j, item.getStateContentType());
                ps.setTimestamp(++j, item.getSavedAt() != null ? Timestamp.valueOf(item.getSavedAt()) : null);
                ps.setString(++j, item.getCheckPointId());
            }

            @Override
            public int getBatchSize() {
                return list.size();
            }
        });
        return result;
    }

    /**
     * 删除
     */
    @Override
    public boolean delete(String id) {
        String sql = "DELETE FROM AI_GRAPHCHECKPOINT WHERE CHECKPOINT_ID = ?";
        int result;
        try {
            result = jdbcTemplate.update(sql, id);
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            throw new ValidationException("删除 检查点 数据 失败。");
        }
        return result > 0;
    }

    /**
     * 根据Id查询
     */
    @Override
    public GraphCheckPoint selectById(String id) {
        String sql = "SELECT * FROM AI_GRAPHCHECKPOINT WHERE CHECKPOINT_ID = ? ";
        try {
            return jdbcTemplate.queryForObject(sql, new GraphCheckPointRowMapper(), id);
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            return null;
        }
    }

    /**
     * 根据查询条件查询单个对象
     */
    @Override
    public GraphCheckPoint selectOneByCriteria(GraphCheckPointCriteria criteria) {
        StringBuffer buffer = new StringBuffer("SELECT * FROM AI_GRAPHCHECKPOINT ");
        List<Object> list = OracleUtils.combinationSql(buffer, createCriteriaSql(criteria), 1, 1);
        try {
            return jdbcTemplate.queryForObject(buffer.toString(), list.toArray(), new GraphCheckPointRowMapper());
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            return null;
        }
    }

    /**
     * 根据查询条件查询对象集合
     */
    @Override
    public List<GraphCheckPoint> selectByCriteria(GraphCheckPointCriteria criteria) {
        StringBuffer buffer = new StringBuffer("SELECT * FROM AI_GRAPHCHECKPOINT ");
        List<Object> list = OracleUtils.combinationSql(buffer, createCriteriaSql(criteria));
        try {
            return jdbcTemplate.query(buffer.toString(), list.toArray(), new GraphCheckPointRowMapper());
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            return null;
        }
    }

    /**
     * 根据查询条件分页查询对象结合
     */
    @Override
    public List<GraphCheckPoint> selectCriteriaByPage(GraphCheckPointCriteria criteria, int pageNum, int pageSize) {
        StringBuffer buffer = new StringBuffer("SELECT * FROM AI_GRAPHCHECKPOINT ");
        List<Object> list = OracleUtils.combinationSql(buffer, createCriteriaSql(criteria), pageNum, pageSize);
        try {
            return jdbcTemplate.query(buffer.toString(), list.toArray(), new GraphCheckPointRowMapper());
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            return null;
        }
    }

    /**
     * 根据条件查询对象总记录数
     */
    @Override
    public Integer selectCountByCriteria(GraphCheckPointCriteria criteria) {
        StringBuffer buffer = new StringBuffer("SELECT COUNT(*) FROM AI_GRAPHCHECKPOINT ");
        List<Object> list = OracleUtils.combinationSql(buffer, createCriteriaSql(criteria));
        int count = jdbcTemplate.queryForObject(buffer.toString(), list.toArray(), int.class);
        return count;
    }

    /**
     * RowMapper
     */
    private class GraphCheckPointRowMapper implements RowMapper<GraphCheckPoint> {
        @Override
        public GraphCheckPoint mapRow(ResultSet rs, int i) throws SQLException {
            return new GraphCheckPoint(
                    rs.getString("CHECKPOINT_ID"),
                    rs.getString("PARENT_CHECKPOINT_ID"),
                    rs.getString("THREAD_ID"),
                    rs.getString("NODE_ID"),
                    rs.getString("NEXT_NODE_ID"),
                    rs.getString("STATE_DATA"),
                    rs.getString("STATE_CONTENT_TYPE"),
                    rs.getTimestamp("SAVED_AT").toLocalDateTime()
            );
        }
    }

    /**
     * 创建查询条件
     */
    private Map<String, Object> createCriteriaSql(GraphCheckPointCriteria criteria) {
        Map<String, Object> andMap = new LinkedHashMap<>();
        if (criteria == null)
            return andMap;

        //
        if (criteria.byCheckPointId())
            andMap.put(criteria.getCheckPointId() == null ? " CHECKPOINT_ID IS NULL " : " CHECKPOINT_ID = ? ", criteria.getCheckPointId());
        //
        if (criteria.byParentCheckPointId())
            andMap.put(criteria.getParentCheckPointId() == null ? " PARENT_CHECKPOINT_ID IS NULL " : " PARENT_CHECKPOINT_ID = ? ", criteria.getParentCheckPointId());
        //
        if (criteria.byThreadId())
            andMap.put(criteria.getThreadId() == null ? " THREAD_ID IS NULL " : " THREAD_ID = ? ", criteria.getThreadId());
        //
        if (criteria.byNodeId())
            andMap.put(criteria.getNodeId() == null ? " NODE_ID IS NULL " : " NODE_ID = ? ", criteria.getNodeId());
        //
        if (criteria.byNextNodeId())
            andMap.put(criteria.getNextNodeId() == null ? " NEXT_NODE_ID IS NULL " : " NEXT_NODE_ID = ? ", criteria.getNextNodeId());
        return andMap;
    }

}
