//! generating 状态 RAII guard。
//!
//! B-Phase2: ConvState 切无锁 ConvStateStore(不竞争 session lock,删 800ms fallback)。
//! 治卡死连环:AiCompleted 延迟 / 工具后中断 / 第二条进队列同源根因。

use tauri::{AppHandle, Emitter, Manager};

use crate::commands::ai::AiChatEvent;

use super::conv_state::ConvState;

/// generating 复位 RAII guard。
///
/// ConvState 经无锁 [`ConvStateStore`](super::conv_state::ConvStateStore) 迁移(不竞争 session
/// lock)。正常退出显式 `reset()`;异常退出 `Drop` 兜底迁移 Idle。`disarm` 解除 Drop 兜底
/// (审批等待保持 Generating,续跑新 guard.new 重新迁移)。
pub(super) struct GeneratingGuard {
    conv_id: String,
    done: bool,
    app_handle: AppHandle,
}

impl GeneratingGuard {
    pub(super) fn new(conv_id: String, app_handle: AppHandle) -> Self {
        let guard = Self {
            conv_id,
            done: false,
            app_handle: app_handle.clone(),
        };
        guard.transition(ConvState::Generating);
        guard
    }

    /// 复位 Idle(emit 前调,保证前端收事件时后端已 Idle)。幂等。
    pub(super) async fn reset(&mut self) {
        if !self.done {
            self.done = true;
            self.transition(ConvState::Idle);
        }
    }

    /// 解除 Drop 兜底(审批等待保持 Generating)。
    pub(super) fn disarm(&mut self) {
        self.done = true;
    }

    /// 迁移 ConvState + emit AiConvStateChanged(经无锁 ConvStateStore,同步无 await)。
    fn transition(&self, target: ConvState) {
        let conv_states = self
            .app_handle
            .state::<crate::state::AppState>()
            .conv_states
            .clone();
        let ev = match conv_states.transition(&self.conv_id, target) {
            Ok(ns) => Some(AiChatEvent::AiConvStateChanged {
                conv_state: ns,
                conversation_id: Some(self.conv_id.clone()),
            }),
            Err(e) => {
                tracing::warn!(
                    conv_id = %self.conv_id,
                    error = %e,
                    "[ai] guard ConvState 迁移非法"
                );
                None
            }
        };
        if let Some(ev) = ev {
            let _ = self.app_handle.emit("ai-chat-event", ev.clone());
            let _ = self
                .app_handle
                .state::<crate::state::AppState>()
                .ai_event_bus
                .publish_event(ev);
        }
    }
}

impl Drop for GeneratingGuard {
    fn drop(&mut self) {
        if !self.done {
            self.transition(ConvState::Idle);
        }
    }
}

// ConvState 迁移语义单测见 conv_state.rs(ConvStateStore + ConvState::transition_to)。
// guard struct 委托 ConvStateStore,无独立逻辑,不重复单测。
