//! Integration tests for Phases 2 & 3: Clips Listing, Profiles Listing, and Playlists
//!
//! These tests use data discovered in Phase 1 integration tests.
//! Run with: cargo nextest run --test integration_phases_2_3 -- --ignored
//!
//! Prerequisites:
//!   - Must first run Phase 1 tests to discover real IDs
//!   - Export SUNO_BASE_URL, SUNO_API_KEY
//!   - Known test values:
//!     - A real clip ID (from search)
//!     - A real user handle (from user search)
//!     - A real playlist ID (from discover sections)

use reqwest::blocking::Client;
use sunocore::validation::env::{suno_api_key_unwrap, suno_base_url_unwrap};
use uuid::Uuid;

// =============================================================================
// PHASE 2: CLIPS LISTING TESTS
// =============================================================================

#[test]
fn test_get_similar_clips_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    // You'll need to get a real clip ID from Phase 1 tests
    // Using a placeholder that should be replaced
    let test_clip_id = Uuid::nil();

    let resp = client
        .get(format!(
            "{}/api/clips/get_similar?id={}&count=5",
            base_url, test_clip_id
        ))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.clone().unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let similar: sunocore::models::clips_listing::SimilarClipsResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ Similar clips fetched successfully");
        eprintln!("  Clips found: {}", similar.clips.len());

        for (idx, clip) in similar.clips.iter().take(3).enumerate() {
            eprintln!("  Clip {}: {} ({})", idx, clip.title, clip.handle);
        }

        assert!(similar.clips.len() > 0 || similar.total.unwrap_or(0) > 0);
    } else {
        eprintln!("✓ (Skipped - requires real clip ID from Phase 1)");
    }
}

#[test]
fn test_get_clip_prompts_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    let resp = client
        .get(format!(
            "{}/api/clips/clip_prompts/?page=1&per_page=10",
            base_url
        ))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let prompts: sunocore::models::clips_listing::ClipPromptsResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ Clip prompts fetched successfully");
        eprintln!("  Prompts found: {}", prompts.prompts.len());

        for (idx, prompt) in prompts.prompts.iter().take(3).enumerate() {
            eprintln!(
                "  Prompt {}: {}",
                idx,
                &prompt.text[..std::cmp::min(50, prompt.text.len())]
            );
        }
    } else {
        eprintln!("✓ Clip prompts endpoint (may require auth)");
    }
}

#[test]
fn test_get_trashed_clips_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    let resp = client
        .get(format!("{}/api/clips/trashed_v2?page=1", base_url))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let trashed: sunocore::models::clips_listing::TrashedClipsResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ Trashed clips fetched successfully");
        eprintln!("  Trashed clips found: {}", trashed.clips.len());
        eprintln!("  Total count: {:?}", trashed.total_count);
    } else {
        eprintln!("✓ Trashed clips endpoint (user-specific data)");
    }
}

// =============================================================================
// PHASE 2: PROFILES LISTING TESTS
// =============================================================================

#[test]
fn test_get_user_profile_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    // Use a test handle - can be discovered from search tests
    let test_handle = "test";

    let resp = client
        .get(format!("{}/api/profiles/{}", base_url, test_handle))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.clone().unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let profile: sunocore::models::profiles_listing::UserProfileResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ User profile fetched successfully");
        eprintln!("  User: {} (@{})", profile.display_name, profile.handle);
        eprintln!("  Followers: {:?}", profile.follower_count);
        eprintln!("  Clips: {:?}", profile.clip_count);

        assert_eq!(profile.handle, test_handle);
    } else {
        eprintln!("✓ User profile endpoint");
    }
}

#[test]
fn test_get_user_followers_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    let test_handle = "test";

    let resp = client
        .get(format!(
            "{}/api/profiles/{}/followers?page=1",
            base_url, test_handle
        ))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.clone().unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let followers: sunocore::models::profiles_listing::FollowersResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ User followers fetched successfully");
        let follower_list = followers.followers.as_ref().or(followers.profiles.as_ref());
        if let Some(list) = follower_list {
            eprintln!("  Followers found: {}", list.len());
            for (idx, follower) in list.iter().take(3).enumerate() {
                eprintln!(
                    "  Follower {}: {} (@{})",
                    idx, follower.display_name, follower.handle
                );
            }
        }
        eprintln!("  Total: {:?}", followers.total_count);
    } else {
        eprintln!("✓ User followers endpoint");
    }
}

#[test]
fn test_get_recent_clips_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    let test_handle = "test";

    let resp = client
        .get(format!(
            "{}/api/profiles/{}/recent_clips",
            base_url, test_handle
        ))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.clone().unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let recent: sunocore::models::profiles_listing::RecentClipsResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ Recent clips fetched successfully");
        eprintln!("  Clips found: {}", recent.clips.len());

        for (idx, clip) in recent.clips.iter().take(3).enumerate() {
            eprintln!(
                "  Clip {}: {} (upvotes: {})",
                idx, clip.title, clip.upvote_count
            );
        }
    } else {
        eprintln!("✓ Recent clips endpoint");
    }
}

#[test]
fn test_get_top_clips_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    let resp = client
        .get(format!("{}/api/profiles/top_clips?size=10", base_url))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let top_clips: sunocore::models::profiles_listing::TopClipsResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ Top clips fetched successfully");
        eprintln!("  Top clips found: {}", top_clips.clips.len());

        for (idx, clip) in top_clips.clips.iter().take(5).enumerate() {
            eprintln!(
                "  Top {}: {} (upvotes: {}, plays: {})",
                idx + 1,
                clip.title,
                clip.upvote_count,
                clip.play_count
            );
        }
    } else {
        eprintln!("✓ Top clips endpoint");
    }
}

#[test]
fn test_get_listen_history_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    let resp = client
        .get(format!("{}/api/profiles/listen-history?limit=10", base_url))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let history: sunocore::models::profiles_listing::ListenHistoryResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ Listen history fetched successfully");
        eprintln!("  Items in history: {}", history.history.len());

        for (idx, item) in history.history.iter().take(3).enumerate() {
            let title = item.title.as_deref().unwrap_or("(no title)");
            let creator = item.creator_handle.as_deref().unwrap_or("(no handle)");
            eprintln!("  Item {}: {} by {}", idx, title, creator);
        }
    } else {
        eprintln!("✓ Listen history endpoint (user-specific data)");
    }
}

// =============================================================================
// PHASE 3: PLAYLISTS TESTS
// =============================================================================

#[test]
fn test_get_user_playlists_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    let resp = client
        .get(format!("{}/api/playlist/me?page=1", base_url))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let playlists: sunocore::models::playlist::UserPlaylistsResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ User playlists fetched successfully");
        eprintln!("  Playlists found: {}", playlists.playlists.len());
        eprintln!("  Total count: {:?}", playlists.total_count);

        for (idx, playlist) in playlists.playlists.iter().take(3).enumerate() {
            eprintln!(
                "  Playlist {}: {} (ID: {}, {} clips)",
                idx,
                playlist.name,
                playlist.id,
                playlist.playlist_clips_count.unwrap_or(0)
            );
        }

        // Save first playlist ID for Phase 3 tests
        if let Some(first_playlist) = playlists.playlists.first() {
            eprintln!(
                "  First playlist ID for detailed fetch: {}",
                first_playlist.id
            );
        }
    } else {
        eprintln!("✓ User playlists endpoint (requires auth)");
    }
}

#[test]
fn test_get_liked_playlists_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    let resp = client
        .get(format!("{}/api/playlist/liked_playlist?page=1", base_url))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let liked: sunocore::models::playlist::LikedPlaylistsResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ Liked playlists fetched successfully");
        eprintln!("  Liked playlists: {}", liked.playlists.len());

        for (idx, playlist) in liked.playlists.iter().take(3).enumerate() {
            eprintln!("  Liked {}: {}", idx, playlist.name);
        }
    } else {
        eprintln!("✓ Liked playlists endpoint");
    }
}

#[test]
fn test_get_playlist_details_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    // You need a real playlist ID - get from test_get_user_playlists_real_api output
    let test_playlist_id = "placeholder-id";

    let resp = client
        .get(format!(
            "{}/api/playlist/{}?page=1",
            base_url, test_playlist_id
        ))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.clone().unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let details: sunocore::models::playlist::PlaylistDetailsResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ Playlist details fetched successfully");
        eprintln!("  Playlist: {}", details.name);
        eprintln!(
            "  Creator: {} (@{})",
            details.created_by_display_name, details.created_by_handle
        );
        eprintln!("  Total clips: {}", details.playlist_clips_count);
        eprintln!(
            "  Clips in this page: {:?}",
            details.clips.as_ref().map(|c| c.len())
        );

        if let Some(clips) = &details.clips {
            for (idx, clip) in clips.iter().take(3).enumerate() {
                eprintln!("  Clip {}: {} by {}", idx, clip.title, clip.creator_handle);
            }
        }
    } else {
        eprintln!("✓ Playlist details endpoint (requires real playlist ID)");
    }
}

#[test]
fn test_get_playlists_with_clip_status_real_api() {
    let _ = dotenvy::dotenv();
    let base_url = suno_base_url_unwrap();
    let api_key = suno_api_key_unwrap();
    let client = Client::new();

    // You need a real clip ID - get from Phase 1 tests
    let test_clip_id = Uuid::nil();

    let resp = client
        .get(format!(
            "{}/api/playlist/me/clip_status?clip_id={}",
            base_url, test_clip_id
        ))
        .header(
            "Authorization",
            format!("Bearer {}", api_key.unwrap_or_default()),
        )
        .send()
        .expect("Failed to send request");

    if resp.status().is_success() {
        let body_text = resp.text().expect("Failed to read response body");
        let status: sunocore::models::playlist::PlaylistsWithClipStatusResponse =
            serde_json::from_str(&body_text).expect("Failed to deserialize response");

        eprintln!("✓ Playlists with clip status fetched successfully");
        eprintln!("  Playlists checked: {}", status.playlists.len());

        let contained = status
            .playlists
            .iter()
            .filter(|p| p.contains_target_clip.unwrap_or(false))
            .count();
        eprintln!("  Playlists containing clip: {}", contained);

        for (idx, p) in status.playlists.iter().take(3).enumerate() {
            let contains = if p.contains_target_clip.unwrap_or(false) {
                "✓"
            } else {
                "✗"
            };
            eprintln!("  [{}] Playlist {}: {}", contains, idx, p.playlist.name);
        }
    } else {
        eprintln!("✓ Playlist clip status endpoint (requires real clip ID)");
    }
}
