//! generating 状态 RAII guard。
//!
//! B-Phase2: ConvState 切无锁 ConvStateStore(不竞争 session lock,删 800ms fallback)。
//! 治卡死连环:AiCompleted 延迟 / 工具后中断 / 第二条进队列同源根因。
//!
//! F1 并发 epoch 加固(2026-08-05):guard 持 `loop_epoch` Arc + 本 loop 捕获的 `my_epoch`,
//! `reset()` / `Drop` 只在本 loop 仍是 owner(epoch 匹配)时迁移 ConvState→Idle。
//! 旧 loop(被 force_send/新 loop 接管,epoch 已变)的复位**跳过**——否则旧 loop 收尾会
//! 把新 loop 的 Generating 复位成 Idle,致新 loop 状态机被破坏(同 conv 双 loop 竞态 F1)。

use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;

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 重新迁移)。
///
/// epoch 语义:`loop_epoch` 是 per_conv 的并发 owner token(每 spawn 新 loop 前 fetch_add(1));
/// `my_epoch` 是本 guard 对应 loop 捕获的 epoch。复位只认 owner(epoch 匹配),
/// 旧 loop 复位跳过(防 clobber 新 loop 状态)。
pub(super) struct GeneratingGuard {
    conv_id: String,
    done: bool,
    /// per_conv.loop_epoch 引用(锁无关原子读,owner 判定用)。
    loop_epoch: Arc<AtomicU64>,
    /// 本 loop 捕获的 epoch。
    my_epoch: u64,
    app_handle: AppHandle,
}

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

    /// 复位 Idle(emit 前调,保证前端收事件时后端已 Idle)。幂等。
    ///
    /// 只认 owner:本 loop epoch 匹配当前 loop_epoch 才迁移 Idle;
    /// 不匹配(旧 loop)则仅置 done(跳过迁移,防 clobber 新 loop 的 Generating)。
    pub(super) async fn reset(&mut self) {
        if self.done {
            return;
        }
        self.done = true;
        if self.loop_epoch.load(Ordering::SeqCst) == self.my_epoch {
            self.transition(ConvState::Idle);
        } else {
            tracing::debug!(
                conv_id = %self.conv_id,
                my_epoch = self.my_epoch,
                current_epoch = self.loop_epoch.load(Ordering::SeqCst),
                "[ai] 旧 loop guard reset 跳过(已被新 loop 接管,不复位新 Generating)"
            );
        }
    }

    /// 解除 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 {
            return;
        }
        // 只认 owner:epoch 匹配才 Drop 兜底复位 Idle;旧 loop(epoch 已变)跳过,
        // 避免 panic/异常退出时把新 loop 的 Generating clobber 成 Idle。
        if self.loop_epoch.load(Ordering::SeqCst) == self.my_epoch {
            self.transition(ConvState::Idle);
        } else {
            tracing::debug!(
                conv_id = %self.conv_id,
                my_epoch = self.my_epoch,
                current_epoch = self.loop_epoch.load(Ordering::SeqCst),
                "[ai] 旧 loop guard Drop 跳过(已被新 loop 接管,不复位新 Generating)"
            );
        }
    }
}

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