//! End-to-end check of the real pipeline: Takeout CSV -> live Atom feeds ->
//! SQLite -> feed query. Hits the network, so it is ignored by default.
//! Run with: cargo test --test pipeline -- --ignored --nocapture

use flighttube_lib::{db::Db, feed, models::FeedFilter, takeout};

const CSV: &str = include_str!("fixtures/subscriptions.csv");

#[tokio::test]
#[ignore]
async fn full_pipeline_against_live_feeds() {
    let channels = takeout::parse_csv(CSV).expect("CSV should parse");
    println!("parsed {} channels", channels.len());
    assert!(channels.len() >= 10);

    let mut db = Db::open_in_memory_pub().expect("db");
    db.upsert_channels(&channels).unwrap();

    let http = reqwest::Client::builder()
        .user_agent("FlightTube/0.1 (+desktop)")
        .timeout(std::time::Duration::from_secs(20))
        .build()
        .unwrap();

    let mut total = 0;
    for c in &channels {
        match feed::fetch_channel(&http, &c.id).await {
            Ok(v) => {
                println!("  {:<30} {} videos", c.title, v.len());
                total += v.len();
                db.upsert_videos(&v).unwrap();
            }
            Err(e) => println!("  {:<30} FAILED: {e}", c.title),
        }
    }
    assert!(total > 50, "expected a real feed, got {total} videos");

    let all = db.list_feed(&FeedFilter::default()).unwrap();
    println!("\nfeed rows: {}", all.len());

    // The whole point: newest first, across all channels.
    for w in all.windows(2) {
        assert!(w[0].published >= w[1].published, "feed must be newest-first");
    }
    println!("top 5 newest across all subscriptions:");
    for item in all.iter().take(5) {
        println!(
            "  [{}] {} — {}",
            item.channel_title,
            item.title.chars().take(60).collect::<String>(),
            item.published
        );
    }

    let no_shorts = db
        .list_feed(&FeedFilter { hide_shorts: true, ..Default::default() })
        .unwrap();
    println!("\nwith shorts hidden: {} (was {})", no_shorts.len(), all.len());
    assert!(no_shorts.len() <= all.len());
    assert!(no_shorts.iter().all(|i| !i.is_short));

    // Nothing is downloaded, so the offline view must be empty.
    let offline = db
        .list_feed(&FeedFilter { downloaded_only: true, ..Default::default() })
        .unwrap();
    assert_eq!(offline.len(), 0, "nothing downloaded yet");
    println!("offline view with no downloads: {} rows (correct)", offline.len());
}
