<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.generator.mapper.front.AiGenerationTaskMapper">

    <resultMap type="AiGenerationTask" id="AiGenerationTaskResult">
        <id property="taskId" column="task_id" />
        <result property="generationId" column="generation_id" />
        <result property="projectId" column="project_id" />
        <result property="userId" column="user_id" />
        <result property="generateType" column="generate_type" />
        <result property="provider" column="provider" />
        <result property="model" column="model" />
        <result property="status" column="status" />
        <result property="requestHash" column="request_hash" />
        <result property="requestPayload" column="request_payload" />
        <result property="resultPayload" column="result_payload" />
        <result property="errorCode" column="error_code" />
        <result property="errorMessage" column="error_message" />
        <result property="attempts" column="attempts" />
        <result property="maxAttempts" column="max_attempts" />
        <result property="nextRetryTime" column="next_retry_time" />
        <result property="lockedBy" column="locked_by" />
        <result property="lockedUntil" column="locked_until" />
        <result property="progress" column="progress" />
        <result property="currentStep" column="current_step" />
        <result property="inputTokens" column="input_tokens" />
        <result property="outputTokens" column="output_tokens" />
        <result property="totalTokens" column="total_tokens" />
        <result property="costCents" column="cost_cents" />
        <result property="startedAt" column="started_at" />
        <result property="finishedAt" column="finished_at" />
        <result property="createTime" column="create_time" />
        <result property="updateTime" column="update_time" />
    </resultMap>

    <sql id="selectAiGenerationTaskVo">
        select task_id, generation_id, project_id, user_id, generate_type, provider, model, status,
               request_hash, request_payload, result_payload, error_code, error_message, attempts, max_attempts,
               next_retry_time, locked_by, locked_until, progress, current_step, input_tokens, output_tokens,
               total_tokens, cost_cents, started_at, finished_at, create_time, update_time
        from front_ai_generation_task
    </sql>

    <select id="selectAiGenerationTaskById" parameterType="Long" resultMap="AiGenerationTaskResult">
        <include refid="selectAiGenerationTaskVo"/>
        where task_id = #{taskId}
    </select>

    <select id="selectTaskForUser" resultMap="AiGenerationTaskResult">
        <include refid="selectAiGenerationTaskVo"/>
        where user_id = #{userId} and project_id = #{projectId} and task_id = #{taskId}
    </select>

    <select id="selectActiveTaskByRequestHash" resultMap="AiGenerationTaskResult">
        <include refid="selectAiGenerationTaskVo"/>
        where user_id = #{userId}
          and project_id = #{projectId}
          and request_hash = #{requestHash}
          and status in ('QUEUED', 'RUNNING', 'RETRY_WAITING')
        order by task_id desc
        limit 1
    </select>

    <select id="selectTasksByProjectId" resultMap="AiGenerationTaskResult">
        <include refid="selectAiGenerationTaskVo"/>
        where user_id = #{userId} and project_id = #{projectId}
        order by task_id desc
    </select>

    <select id="selectClaimableTasks" resultMap="AiGenerationTaskResult">
        <include refid="selectAiGenerationTaskVo"/>
        where status in ('QUEUED', 'RETRY_WAITING')
          and (next_retry_time is null or next_retry_time &lt;= sysdate())
          and (locked_until is null or locked_until &lt; sysdate())
        order by task_id asc
        limit #{limit}
    </select>

    <insert id="insertAiGenerationTask" parameterType="AiGenerationTask" useGeneratedKeys="true" keyProperty="taskId">
        insert into front_ai_generation_task
        <trim prefix="(" suffix=")" suffixOverrides=",">
            generation_id, project_id, user_id, generate_type, provider, model, status, request_hash,
            request_payload, result_payload, error_code, error_message, attempts, max_attempts,
            next_retry_time, locked_by, locked_until, progress, current_step, input_tokens, output_tokens,
            total_tokens, cost_cents, started_at, finished_at, create_time, update_time,
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            #{generationId}, #{projectId}, #{userId}, #{generateType}, #{provider}, #{model}, #{status}, #{requestHash},
            #{requestPayload}, #{resultPayload}, #{errorCode}, #{errorMessage}, #{attempts}, #{maxAttempts},
            #{nextRetryTime}, #{lockedBy}, #{lockedUntil}, #{progress}, #{currentStep}, #{inputTokens}, #{outputTokens},
            #{totalTokens}, #{costCents}, #{startedAt}, #{finishedAt}, sysdate(), sysdate(),
        </trim>
    </insert>

    <update id="updateAiGenerationTask" parameterType="AiGenerationTask">
        update front_ai_generation_task
        <trim prefix="SET" suffixOverrides=",">
            <if test="generationId != null">generation_id = #{generationId},</if>
            <if test="status != null">status = #{status},</if>
            <if test="resultPayload != null">result_payload = #{resultPayload},</if>
            <if test="errorCode != null">error_code = #{errorCode},</if>
            <if test="errorMessage != null">error_message = #{errorMessage},</if>
            <if test="attempts != null">attempts = #{attempts},</if>
            <if test="maxAttempts != null">max_attempts = #{maxAttempts},</if>
            <if test="nextRetryTime != null">next_retry_time = #{nextRetryTime},</if>
            <if test="lockedBy != null">locked_by = #{lockedBy},</if>
            <if test="lockedUntil != null">locked_until = #{lockedUntil},</if>
            <if test="progress != null">progress = #{progress},</if>
            <if test="currentStep != null">current_step = #{currentStep},</if>
            <if test="inputTokens != null">input_tokens = #{inputTokens},</if>
            <if test="outputTokens != null">output_tokens = #{outputTokens},</if>
            <if test="totalTokens != null">total_tokens = #{totalTokens},</if>
            <if test="costCents != null">cost_cents = #{costCents},</if>
            <if test="startedAt != null">started_at = #{startedAt},</if>
            <if test="finishedAt != null">finished_at = #{finishedAt},</if>
            update_time = sysdate(),
        </trim>
        where task_id = #{taskId}
    </update>

    <update id="claimTask">
        update front_ai_generation_task
        set status = 'RUNNING',
            locked_by = #{lockedBy},
            locked_until = date_add(sysdate(), interval 10 minute),
            current_step = '正在启动',
            progress = 5,
            update_time = sysdate()
        where task_id = #{taskId}
          and status in ('QUEUED', 'RETRY_WAITING')
          and (next_retry_time is null or next_retry_time &lt;= sysdate())
          and (locked_until is null or locked_until &lt; sysdate())
    </update>
</mapper>
