//! Integration tests for the fork session flow.
//!
//! These tests verify the complete fork session flow:
//! 1. Fork session data with parent tracking
//! 2. Verify forked session has correct metadata
//! 3. Test worktree creation from worktree types

use agent_client_protocol as acp;
use kigi_shell::sampling::ConversationItem;
use kigi_shell::session::info::Info;
use kigi_shell::session::storage::{JsonlStorageAdapter, StorageAdapter};
use tempfile::TempDir;

/// Helper to create a test session in a temp directory
async fn create_test_session(storage: &JsonlStorageAdapter, session_id: &str, cwd: &str) -> Info {
    let info = Info {
        id: acp::SessionId::new(session_id),
        cwd: cwd.to_string(),
    };

    let model_id = acp::ModelId::new("kigi-code-fast-1");
    storage.init_session(&info, model_id).await.unwrap();

    // Add some chat messages
    let msg = ConversationItem::user("Hello world");
    storage.append_chat_message(&info, &msg).await.unwrap();

    // Add an update
    let notification = acp::SessionNotification::new(
        acp::SessionId::new(session_id),
        acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk::new(acp::ContentBlock::Text(
            acp::TextContent::new("Test response".to_string()),
        ))),
    );
    storage
        .append_update(
            &info,
            &kigi_shell::session::storage::SessionUpdate::Acp(Box::new(notification)),
        )
        .await
        .unwrap();

    info
}

#[tokio::test]
async fn test_fork_session_creates_new_session_with_parent_tracking() {
    let temp_dir = TempDir::new().unwrap();
    let storage = JsonlStorageAdapter::with_root(temp_dir.path().to_path_buf());

    // Create source session
    let source_info = create_test_session(&storage, "source-session-123", "/source/path").await;

    let target_info = Info {
        id: acp::SessionId::new("fork-session-456"),
        cwd: "/new/path".to_string(),
    };

    let options = kigi_shell::session::storage::CopySessionOptions {
        parent_session_id: Some("source-session-123".to_string()),
        new_model_id: Some("kigi-3".to_string()),
        target_prompt_index: None,
        ..Default::default()
    };

    let result = storage
        .copy_session_data(&source_info, &target_info, options)
        .await
        .unwrap();

    // Verify result
    assert_eq!(result.chat_messages_copied, 1);
    assert_eq!(result.updates_copied, 1);

    // Load the forked session and verify metadata
    let loaded = storage.load_session(&target_info).await.unwrap();

    assert_eq!(loaded.summary.info.id.to_string(), "fork-session-456");
    assert_eq!(loaded.summary.info.cwd, "/new/path");
    assert_eq!(loaded.summary.current_model_id, acp::ModelId::new("kigi-3"));
    assert_eq!(
        loaded.summary.parent_session_id,
        Some("source-session-123".to_string())
    );
    assert!(loaded.summary.forked_at.is_some());

    // Verify chat history was copied
    assert_eq!(loaded.chat_history.len(), 1);

    // Verify updates were copied with transformed session ID
    assert_eq!(loaded.updates.len(), 1);
    match &loaded.updates[0] {
        kigi_shell::session::storage::SessionUpdate::Acp(notification) => {
            assert_eq!(notification.session_id.to_string(), "fork-session-456");
        }
        _ => panic!("Expected ACP update"),
    }
}

#[tokio::test]
async fn test_fork_preserves_session_title() {
    let temp_dir = TempDir::new().unwrap();
    let storage = JsonlStorageAdapter::with_root(temp_dir.path().to_path_buf());

    // Create source session
    let source_info = create_test_session(&storage, "titled-session", "/source").await;

    // Update source session with a title
    storage
        .update_session_title(&source_info, "My Important Session".to_string())
        .await
        .unwrap();

    // Fork the session
    let target_info = Info {
        id: acp::SessionId::new("fork-titled"),
        cwd: "/new".to_string(),
    };

    let options = kigi_shell::session::storage::CopySessionOptions {
        parent_session_id: Some("titled-session".to_string()),
        new_model_id: None,
        target_prompt_index: None,
        ..Default::default()
    };

    storage
        .copy_session_data(&source_info, &target_info, options)
        .await
        .unwrap();

    // Load and verify title was preserved (generated_title is the LLM title field).
    let loaded = storage.load_session(&target_info).await.unwrap();
    assert_eq!(loaded.summary.display_title(), "My Important Session");
}
