package tech.easyflow.ai.mapper;

import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import tech.easyflow.ai.entity.DocumentImportSnapshotCleanup;

import java.math.BigInteger;
import java.util.Date;
import java.util.List;

/**
 * 文档导入中间快照清理记录映射层。
 *
 * @author Codex
 * @since 2026-08-04
 */
public interface DocumentImportSnapshotCleanupMapper
    extends BaseMapper<DocumentImportSnapshotCleanup> {

    /**
     * 幂等登记一个快照清理请求。
     *
     * @param record 清理记录
     * @return 新增行数
     */
    @Insert("INSERT IGNORE INTO tb_document_import_snapshot_cleanup "
        + "(id, knowledge_id, document_id, snapshot_type, manifest_path, "
        + "path_hash, phase, attempt_count, next_retry_at, created, modified) "
        + "VALUES (#{id}, #{knowledgeId}, #{documentId}, #{snapshotType}, "
        + "#{manifestPath}, #{pathHash}, #{phase}, #{attemptCount}, "
        + "#{nextRetryAt}, #{created}, #{modified})")
    int insertIgnore(DocumentImportSnapshotCleanup record);

    /**
     * 查询到期且未被有效租约持有的清理记录。
     *
     * @param now 当前时间
     * @param limit 查询上限
     * @return 待处理记录
     */
    @Select("SELECT * FROM tb_document_import_snapshot_cleanup "
        + "WHERE next_retry_at <= #{now} "
        + "AND (execution_token IS NULL OR lease_until < #{now}) "
        + "ORDER BY next_retry_at, id LIMIT #{limit}")
    List<DocumentImportSnapshotCleanup> selectDueRecords(
        @Param("now") Date now,
        @Param("limit") int limit);

    /**
     * 原子领取一条清理记录。
     *
     * @param id 记录 ID
     * @param executionToken 执行令牌
     * @param leaseUntil 租约截止时间
     * @param now 当前时间
     * @return 更新行数
     */
    @Update("UPDATE tb_document_import_snapshot_cleanup SET "
        + "execution_token=#{executionToken}, lease_until=#{leaseUntil}, "
        + "attempt_count=attempt_count + 1, modified=#{now} "
        + "WHERE id=#{id} AND next_retry_at <= #{now} "
        + "AND (execution_token IS NULL OR lease_until < #{now})")
    int claim(
        @Param("id") BigInteger id,
        @Param("executionToken") String executionToken,
        @Param("leaseUntil") Date leaseUntil,
        @Param("now") Date now);

    /**
     * 在分片全部删除后持久化推进到清单删除阶段。
     *
     * @param id 记录 ID
     * @param executionToken 执行令牌
     * @param modified 修改时间
     * @return 更新行数
     */
    @Update("UPDATE tb_document_import_snapshot_cleanup SET "
        + "phase='MANIFEST_PENDING', last_error=NULL, modified=#{modified} "
        + "WHERE id=#{id} AND execution_token=#{executionToken} "
        + "AND phase='PARTS_PENDING'")
    int advanceToManifest(
        @Param("id") BigInteger id,
        @Param("executionToken") String executionToken,
        @Param("modified") Date modified);

    /**
     * 释放失败记录并安排下一次重试。
     *
     * @param id 记录 ID
     * @param executionToken 执行令牌
     * @param nextRetryAt 下次重试时间
     * @param lastError 最近错误
     * @param modified 修改时间
     * @return 更新行数
     */
    @Update("UPDATE tb_document_import_snapshot_cleanup SET "
        + "execution_token=NULL, lease_until=NULL, "
        + "next_retry_at=#{nextRetryAt}, last_error=#{lastError}, "
        + "modified=#{modified} "
        + "WHERE id=#{id} AND execution_token=#{executionToken}")
    int releaseForRetry(
        @Param("id") BigInteger id,
        @Param("executionToken") String executionToken,
        @Param("nextRetryAt") Date nextRetryAt,
        @Param("lastError") String lastError,
        @Param("modified") Date modified);

    /**
     * 删除当前执行令牌已完成的清理记录。
     *
     * @param id 记录 ID
     * @param executionToken 执行令牌
     * @return 删除行数
     */
    @Delete("DELETE FROM tb_document_import_snapshot_cleanup "
        + "WHERE id=#{id} AND execution_token=#{executionToken} "
        + "AND phase='MANIFEST_PENDING'")
    int deleteCompleted(
        @Param("id") BigInteger id,
        @Param("executionToken") String executionToken);
}
