use crate::agent::runloop::ResumeSession;
use crate::agent::runloop::mcp_events;
use crate::agent::runloop::unified::async_mcp_manager::AsyncMcpManager;
use crate::agent::runloop::unified::context_manager::ContextManager;
use crate::agent::runloop::unified::session_setup::IdeContextBridge;
use crate::agent::runloop::unified::state::CtrlCState;
use crate::agent::runloop::unified::tool_call_safety::ToolCallSafetyValidator;
use crate::agent::runloop::unified::tool_catalog::ToolCatalogState;
use crate::agent::runloop::welcome::SessionBootstrap;
use hashbrown::HashMap;
use std::sync::Arc;
use std::sync::atomic::AtomicU64;
use tokio::sync::{Notify, RwLock};
use vtcode_core::acp::ToolPermissionCache;
use vtcode_core::config::PermissionsConfig;
use vtcode_core::core::decision_tracker::DecisionTracker;
use vtcode_core::core::trajectory::TrajectoryLogger;
use vtcode_core::hooks::{LifecycleHookEngine, SessionEndReason};
use vtcode_core::llm::provider as uni;
use vtcode_core::tools::ApprovalRecorder;
use vtcode_core::tools::{ToolRegistry, ToolResultCache};
use vtcode_core::utils::ansi::AnsiRenderer;
use vtcode_core::utils::session_archive::SessionArchive;
use vtcode_core::utils::session_archive::session_workspace_path;
use vtcode_tui::app::{InlineHandle, InlineHeaderContext, InlineSession};

use crate::updater::{StartupUpdateCheck, StartupUpdateNotice};

pub(crate) struct BackgroundTaskGuard {
    handle: Option<tokio::task::JoinHandle<()>>,
}

impl BackgroundTaskGuard {
    pub(crate) fn new(handle: tokio::task::JoinHandle<()>) -> Self {
        Self {
            handle: Some(handle),
        }
    }
}

impl Drop for BackgroundTaskGuard {
    fn drop(&mut self) {
        if let Some(handle) = self.handle.take() {
            handle.abort();
        }
    }
}

pub(crate) struct ToolExecutionContext {
    pub tool_result_cache: Arc<RwLock<ToolResultCache>>,
    pub tool_permission_cache: Arc<RwLock<ToolPermissionCache>>,
    pub permissions_state: Arc<RwLock<PermissionsConfig>>,
    pub approval_recorder: Arc<ApprovalRecorder>,
    pub safety_validator: Arc<ToolCallSafetyValidator>,
    pub circuit_breaker: Arc<vtcode_core::tools::circuit_breaker::CircuitBreaker>,
    pub tool_health_tracker: Arc<vtcode_core::tools::health::ToolHealthTracker>,
    pub rate_limiter: Arc<vtcode_core::tools::adaptive_rate_limiter::AdaptiveRateLimiter>,
    pub validation_cache: Arc<vtcode_core::tools::validation_cache::ValidationCache>,
    pub autonomous_executor: Arc<vtcode_core::tools::autonomous_executor::AutonomousExecutor>,
}

pub(crate) struct SessionMetadataContext {
    pub decision_ledger: Arc<RwLock<DecisionTracker>>,
    pub trajectory: TrajectoryLogger,
    pub telemetry: Arc<vtcode_core::core::telemetry::TelemetryManager>,
    pub error_recovery: Arc<RwLock<vtcode_core::core::agent::error_recovery::ErrorRecoveryState>>,
}

pub(crate) struct SessionState {
    pub session_bootstrap: SessionBootstrap,
    pub startup_update_check: StartupUpdateCheck,
    pub provider_client: Box<dyn uni::LLMProvider>,
    pub tool_registry: ToolRegistry,
    pub tools: Arc<RwLock<Vec<uni::ToolDefinition>>>,
    pub tool_catalog: Arc<ToolCatalogState>,
    pub conversation_history: Vec<uni::Message>,
    pub execution: ToolExecutionContext,
    pub metadata: SessionMetadataContext,
    pub base_system_prompt: String,
    pub full_auto_allowlist: Option<Vec<String>>,
    pub async_mcp_manager: Option<Arc<AsyncMcpManager>>,
    pub mcp_panel_state: mcp_events::McpPanelState,
    pub loaded_skills: Arc<RwLock<HashMap<String, vtcode_core::skills::types::Skill>>>,
}

pub(crate) struct SessionUISetup {
    pub renderer: AnsiRenderer,
    pub session: InlineSession,
    pub handle: InlineHandle,
    pub header_context: InlineHeaderContext,
    pub ide_context_bridge: Option<IdeContextBridge>,
    pub ctrl_c_state: Arc<CtrlCState>,
    pub ctrl_c_notify: Arc<Notify>,
    pub input_activity_counter: Arc<AtomicU64>,
    pub checkpoint_manager: Option<vtcode_core::core::agent::snapshots::SnapshotManager>,
    pub session_archive: Option<SessionArchive>,
    pub lifecycle_hooks: Option<LifecycleHookEngine>,
    pub session_end_reason: SessionEndReason,
    pub context_manager: ContextManager,
    pub default_placeholder: Option<String>,
    pub follow_up_placeholder: Option<String>,
    pub next_checkpoint_turn: usize,
    pub file_palette_task_guard: BackgroundTaskGuard,
    pub background_subprocess_task_guard: Option<BackgroundTaskGuard>,
    pub startup_update_cached_notice: Option<StartupUpdateNotice>,
    pub startup_update_notice_rx: Option<tokio::sync::mpsc::UnboundedReceiver<StartupUpdateNotice>>,
    pub startup_update_task_guard: Option<BackgroundTaskGuard>,
}

pub(crate) async fn build_conversation_history_from_resume(
    resume: Option<&ResumeSession>,
) -> Vec<uni::Message> {
    let Some(session) = resume else {
        return Vec::new();
    };

    let mut history = session.history().to_vec();
    if let Some(workspace_root) = session_workspace_path(session.listing()) {
        crate::agent::runloop::unified::turn::compaction::inject_latest_memory_envelope(
            &workspace_root,
            &session.identifier(),
            &mut history,
        );
    }

    history
}
