package com.agent.management.repository;

import com.agent.management.model.entity.ChatMessage;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.List;
import java.util.Optional;

/**
 * Agent 对话消息 Repository。
 *
 * <p>对应设计文档 §4.3.2。承载消息树（parentId + isActive + branchOrder）的核心查询。</p>
 */
@Repository
public interface ChatMessageRepository extends JpaRepository<ChatMessage, Long> {

    Optional<ChatMessage> findByRunId(String runId);

    /** 列出某会话的所有消息（含历史版本，按创建时间排序） */
    List<ChatMessage> findBySessionIdOrderByCreatedAtAsc(Long sessionId);

    /** 列出同 parent 的所有兄弟消息（用于版本切换器） */
    List<ChatMessage> findByParentIdOrderByBranchOrderAsc(Long parentId);

    /** 取同 parent 下最大 branchOrder（创建新分支时用） */
    @Query("SELECT COALESCE(MAX(m.branchOrder), -1) FROM ChatMessage m WHERE m.parentId = :parentId")
    Integer maxBranchOrderByParent(@Param("parentId") Long parentId);

    /** 把同 parent 的所有消息置为 inactive（切换版本前置操作） */
    @Modifying
    @Query("UPDATE ChatMessage m SET m.isActive = false WHERE m.parentId = :parentId")
    int deactivateSiblings(@Param("parentId") Long parentId);

    /**
     * 批量激活指定 id 集合的消息（用于版本切换：只激活 target 到 root 的主链路）。
     *
     * <p>配合 {@link #deactivateAllBySession(Long)} 使用：先全 session inactive，
     * 再用此方法只激活主路径上的消息，避免出现"旧分支子树仍 active + 新分支也 active"
     * 的混乱状态。</p>
     */
    @Modifying
    @Query("UPDATE ChatMessage m SET m.isActive = true WHERE m.id IN :ids")
    int activateByIds(@Param("ids") Collection<Long> ids);

    /** 把指定会话的所有 ASSISTANT 消息置为 inactive（重置会话时使用，保留作为历史可见） */
    @Modifying
    @Query("UPDATE ChatMessage m SET m.isActive = false WHERE m.sessionId = :sessionId AND m.role = 'ASSISTANT'")
    int deactivateAllAssistants(@Param("sessionId") Long sessionId);

    /** 把指定会话的所有消息置为 inactive（重置会话使用，等价于"软清空"对话） */
    @Modifying
    @Query("UPDATE ChatMessage m SET m.isActive = false WHERE m.sessionId = :sessionId")
    int deactivateAllBySession(@Param("sessionId") Long sessionId);

    /** 取会话最近一条激活消息（用于自动标题取首条 user 消息） */
    Optional<ChatMessage> findFirstBySessionIdAndRoleAndIsActiveTrueOrderByCreatedAtAsc(Long sessionId, String role);

    /** 取会话最近一条激活的 ASSISTANT RUNNING 消息（用于刷新页面后恢复 SSE 流） */
    Optional<ChatMessage> findFirstBySessionIdAndRoleAndStatusAndIsActiveTrueOrderByCreatedAtDesc(
            Long sessionId, String role, String status);

    /** 取某会话当前激活分支的所有消息（按创建时间排序） */
    @Query("SELECT m FROM ChatMessage m WHERE m.sessionId = :sessionId AND m.isActive = true ORDER BY m.createdAt ASC")
    List<ChatMessage> findActiveBranch(@Param("sessionId") Long sessionId);

    /** 标记消息成功并写入最终回复文本（避免 read-then-write，单条 UPDATE） */
    @Modifying
    @Query("UPDATE ChatMessage m SET m.status = 'SUCCESS', m.content = :finalText, m.completedAt = :ts WHERE m.id = :id")
    int markSuccess(@Param("id") Long id, @Param("finalText") String finalText, @Param("ts") java.time.LocalDateTime ts);

    /** 标记消息失败并写入错误信息 */
    @Modifying
    @Query("UPDATE ChatMessage m SET m.status = 'FAILED', m.error = :error, m.completedAt = :ts WHERE m.id = :id")
    int markFailed(@Param("id") Long id, @Param("error") String error, @Param("ts") java.time.LocalDateTime ts);
}
