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.Session;
import com.infoepoch.pms.agent.platform.chat.domain.irepository.ISessionRepository;
import com.infoepoch.pms.agent.platform.chat.domain.irepository.SessionCriteria;
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;

/**
 * 对话会话表仓储实现
 */
@Repository
public class SessionRepository implements ISessionRepository {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 新增
     */
    @Override
    public boolean insert(Session entity) {
        String sql = "INSERT INTO AI_SESSIONS(ID, USER_ID, STATUS, CREATED_AT, UPDATED_AT, TITLE, CHATBOT_ID, ACTIVE_THREAD_ID, CONTEXT_RESET_PENDING) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
        int result;
        try {
            result = jdbcTemplate.update(sql, entity.getId(), entity.getUserId(), entity.getStatus(), entity.getCreatedAt() != null ? Timestamp.valueOf(entity.getCreatedAt()) : null, entity.getUpdatedAt() != null ? Timestamp.valueOf(entity.getUpdatedAt()) : null, entity.getTitle(), entity.getChatBotId(), entity.getActiveThreadId(), entity.isContextResetPending());
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            throw new ValidationException("新增 对话会话表 数据 失败。");
        }
        return result > 0;
    }

    /**
     * 更新
     */
    @Override
    public boolean update(Session entity) {
        String sql = "UPDATE AI_SESSIONS SET USER_ID = ?, STATUS = ?, CREATED_AT = ?, UPDATED_AT = ?, TITLE = ?, CHATBOT_ID = ?, ACTIVE_THREAD_ID = ?, CONTEXT_RESET_PENDING = ? WHERE ID = ?";
        int result;
        try {
            result = jdbcTemplate.update(sql, entity.getUserId(), entity.getStatus(), entity.getCreatedAt() != null ? Timestamp.valueOf(entity.getCreatedAt()) : null, entity.getUpdatedAt() != null ? Timestamp.valueOf(entity.getUpdatedAt()) : null, entity.getTitle(), entity.getChatBotId(), entity.getActiveThreadId(), entity.isContextResetPending(), entity.getId());
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            throw new ValidationException("更新 对话会话表 数据 失败。");
        }
        return result >= 0;
    }

    /**
     * 批量新增
     */
    public int[] batchInsert(List<Session> list) {
        String sql = "INSERT INTO AI_SESSIONS(ID, USER_ID, STATUS, CREATED_AT, UPDATED_AT, TITLE, CHATBOT_ID, ACTIVE_THREAD_ID, CONTEXT_RESET_PENDING) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
        int[] result = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                int j = 0;
                Session item = list.get(i);
                ps.setString(++j, item.getId());
                ps.setString(++j, item.getUserId());
                ps.setString(++j, item.getStatus());
                ps.setTimestamp(++j, item.getCreatedAt() != null ? Timestamp.valueOf(item.getCreatedAt()) : null);
                ps.setTimestamp(++j, item.getUpdatedAt() != null ? Timestamp.valueOf(item.getUpdatedAt()) : null);
                ps.setString(++j, item.getTitle());
                ps.setString(++j, item.getChatBotId());
                ps.setString(++j, item.getActiveThreadId());
                ps.setBoolean(++j, item.isContextResetPending());
            }

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

    /**
     * 批量更新
     */
    public int[] batchUpdate(List<Session> list) {
        String sql = "UPDATE AI_SESSIONS SET USER_ID = ?, STATUS = ?, CREATED_AT = ?, UPDATED_AT = ?, TITLE = ?, CHATBOT_ID = ?, ACTIVE_THREAD_ID = ?, CONTEXT_RESET_PENDING = ? WHERE ID = ? ";
        int[] result = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                int j = 0;
                Session item = list.get(i);
                ps.setString(++j, item.getUserId());
                ps.setString(++j, item.getStatus());
                ps.setTimestamp(++j, item.getCreatedAt() != null ? Timestamp.valueOf(item.getCreatedAt()) : null);
                ps.setTimestamp(++j, item.getUpdatedAt() != null ? Timestamp.valueOf(item.getUpdatedAt()) : null);
                ps.setString(++j, item.getTitle());
                ps.setString(++j, item.getChatBotId());
                ps.setString(++j, item.getActiveThreadId());
                ps.setBoolean(++j, item.isContextResetPending());
                ps.setString(++j, item.getId());
            }

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

    /**
     * 删除
     */
    @Override
    public boolean delete(String id) {
        String sql = "DELETE FROM AI_SESSIONS WHERE 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 Session selectById(String id) {
        String sql = "SELECT * FROM AI_SESSIONS WHERE ID = ? ";
        try {
            return jdbcTemplate.queryForObject(sql, new SessionRowMapper(), id);
        } catch (Exception e) {
            LogHelper.error(this,this.getClass().getName(),e);
            return null;
        }
    }

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

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

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

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

    /**
     * RowMapper
     */
    private class SessionRowMapper implements RowMapper<Session> {
        @Override
        public Session mapRow(ResultSet rs, int i) throws SQLException {
            return new Session(
                    rs.getString("ID"),
                    rs.getString("USER_ID"),
                    rs.getString("CHATBOT_ID"),
                    rs.getString("STATUS"),
                    rs.getString("TITLE"),
                    rs.getString("ACTIVE_THREAD_ID"),
                    rs.getObject("CONTEXT_RESET_PENDING") != null ? rs.getBoolean("CONTEXT_RESET_PENDING") : false,
                    rs.getTimestamp("CREATED_AT").toLocalDateTime(),
                    rs.getTimestamp("UPDATED_AT").toLocalDateTime()
            );
        }
    }

    /**
     * 创建查询条件
     */
    private Map<String, Object> createCriteriaSql(SessionCriteria criteria) {
        Map<String, Object> andMap = new LinkedHashMap<>();
        if (criteria == null)
            return andMap;
        //if (criteria.byId())
        //    andMap.put(criteria.getId() == null ? " T_Id IS NULL " : " T_Id = ? ", criteria.getId());

        //用户标识，由调用方传入，不做格式约束
        if (criteria.byUserId())
            andMap.put(criteria.getUserId() == null ? " USER_ID IS NULL " : " USER_ID = ? ", criteria.getUserId());
        //active / completed / abandoned
        if (criteria.byStatus())
            andMap.put(criteria.getStatus() == null ? " STATUS IS NULL " : " STATUS = ? ", criteria.getStatus());
        //会话标题
        if (criteria.byTitle())
            andMap.put(criteria.getTitle() == null ? " TITLE IS NULL " : " TITLE = ? ", criteria.getTitle());
        //会话标题（LIKE）
        if (criteria.byTitleContain())
            andMap.put(" TITLE LIKE ? ", "%" + criteria.getTitleContain() + "%");
        //所属聊天机器人主键
        if (criteria.byChatbotId())
            andMap.put(criteria.getChatbotId() == null ? " CHATBOT_ID IS NULL " : " CHATBOT_ID = ? ", criteria.getChatbotId());
        //当前活跃上下文线程 ID
        if (criteria.byActiveThreadId())
            andMap.put(criteria.getActiveThreadId() == null ? " ACTIVE_THREAD_ID IS NULL " : " ACTIVE_THREAD_ID = ? ", criteria.getActiveThreadId());
        //是否已标记清除上下文待生效
        if (criteria.byContextResetPending())
            andMap.put(criteria.getContextResetPending() == null ? " CONTEXT_RESET_PENDING IS NULL " : " CONTEXT_RESET_PENDING = ? ", criteria.getContextResetPending());
        return andMap;
    }

}
