use std::time::Duration;

use dotenvy::dotenv;
use reqwest::blocking::Client;
use reqwest::header::{AUTHORIZATION, CONTENT_TYPE, HeaderMap, HeaderValue};
use sunocore::models::feed::{
    FeedFilters, FeedRequest, FeedResponse, PresenceFilter, WorkspaceFilter,
};
use sunocore::validation::env::{suno_api_key_unwrap, suno_base_url_unwrap, workspace_id_unwrap};

// Integration test: fetch from <SUNO_BASE_URL>/api/feed/v3
// and ensure it deserializes into FeedResponse.
#[test]
fn fetch_and_deserialize_feed() {
    // Load .env for SUNO_BASE_URL and SUNO_API_KEY
    let _ = dotenv();

    let base = suno_base_url_unwrap();
    let workspace_uuid = workspace_id_unwrap();

    let url = format!("{}/api/feed/v3", base.trim_end_matches('/'));

    let mut headers = HeaderMap::new();
    headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));

    let api_key = suno_api_key_unwrap();

    if let Some(api_key) = api_key.as_ref() {
        // Send both common auth styles to maximize compatibility with local/staging
        headers.insert(
            AUTHORIZATION,
            HeaderValue::from_str(&format!("Bearer {}", api_key)).expect("valid header"),
        );
        headers.insert(
            "X-Api-Key",
            HeaderValue::from_str(api_key).expect("valid header"),
        );
    }

    let client = Client::builder()
        .default_headers(headers)
        .timeout(Duration::from_secs(20))
        .build()
        .expect("build http client");

    // Create request body
    let request_body = FeedRequest {
        cursor: None,
        limit: 20,
        filters: FeedFilters {
            disliked: "False".to_string(),
            trashed: "False".to_string(),
            from_studio_project: PresenceFilter {
                presence: "False".to_string(),
            },
            stem: PresenceFilter {
                presence: "False".to_string(),
            },
            workspace: WorkspaceFilter {
                presence: "True".to_string(),
                workspace_id: workspace_uuid,
            },
        },
    };

    let resp = client
        .post(&url)
        .json(&request_body)
        .send()
        .unwrap_or_else(|e| panic!("request to {} failed: {}", url, e));

    assert!(
        resp.status().is_success(),
        "HTTP {} fetching {}. Did you set SUNO_API_KEY and run the backend at SUNO_BASE_URL?",
        resp.status(),
        url
    );

    // Read text then deserialize for better error messages when schema drifts.
    let body = resp
        .text()
        .unwrap_or_else(|e| panic!("reading body from {} failed: {}", url, e));
    let feed: FeedResponse = serde_json::from_str(&body).unwrap_or_else(|e| {
        panic!(
            "deserialization failed for {}: {}\nbody: {}",
            url,
            e,
            &body[..body.len().min(2000)]
        )
    });

    // Basic sanity checks
    println!("Fetched {} clips from feed", feed.clips.len());

    if feed.clips.len() > 0 {
        let first_clip = &feed.clips[0];
        assert!(
            !first_clip.id.to_string().is_empty(),
            "clip id should not be empty"
        );
        assert!(
            !first_clip.audio_url.is_empty(),
            "audio_url should not be empty"
        );
        assert!(
            !first_clip.user_id.to_string().is_empty(),
            "user_id should not be empty"
        );
        println!("First clip: {} ({})", first_clip.title, first_clip.id);
        println!(
            "  Model: {} / {}",
            first_clip.major_model_version, first_clip.model_name
        );
        println!("  Duration: {}s", first_clip.metadata.duration);
        if let Some(ref tags) = first_clip.display_tags {
            println!("  Tags: {}", tags);
        }
    }
}
