//! Integration tests for the labeler HTTP stage using snapshot tests.

mod common;

use atproto_devtool::commands::test::labeler::http::run;
use common::FakeRawHttpTee;

/// Helper to render a report to a string for snapshot testing.
fn render_report_to_string(
    report: &atproto_devtool::commands::test::labeler::report::LabelerReport,
) -> String {
    let mut buf = Vec::new();
    report
        .render(
            &mut buf,
            &atproto_devtool::commands::test::labeler::report::RenderConfig { no_color: true },
        )
        .expect("render failed");
    String::from_utf8(buf).expect("invalid utf-8")
}

#[tokio::test]
async fn http_healthy_renders_all_ok() {
    let tee = FakeRawHttpTee::new();
    // Load fixture pages with real labels and pagination.
    let first_page = include_bytes!("fixtures/labeler/http/healthy/first_page.json").to_vec();
    let second_page = include_bytes!("fixtures/labeler/http/healthy/second_page.json").to_vec();

    tee.add_response(None, 200, first_page);
    tee.add_response(Some("cursor1"), 200, second_page);

    let output = run(&tee).await;

    // Build a minimal report for snapshot testing.
    let mut report = atproto_devtool::commands::test::labeler::report::LabelerReport::new(
        atproto_devtool::commands::test::labeler::report::ReportHeader {
            target: "https://example.com".to_string(),
            resolved_did: None,
            pds_endpoint: None,
            labeler_endpoint: Some("https://example.com".to_string()),
        },
    );

    for result in output.results {
        report.record(result);
    }
    report.finish();

    let rendered = render_report_to_string(&report);
    insta::assert_snapshot!(rendered);
}

#[tokio::test]
async fn http_empty_labeler_emits_advisory() {
    let tee = FakeRawHttpTee::new();
    let empty_page = include_bytes!("fixtures/labeler/http/empty/first_page.json").to_vec();

    tee.add_response(None, 200, empty_page);

    let output = run(&tee).await;

    let mut report = atproto_devtool::commands::test::labeler::report::LabelerReport::new(
        atproto_devtool::commands::test::labeler::report::ReportHeader {
            target: "https://example.com".to_string(),
            resolved_did: None,
            pds_endpoint: None,
            labeler_endpoint: Some("https://example.com".to_string()),
        },
    );

    for result in output.results {
        report.record(result);
    }
    report.finish();

    let rendered = render_report_to_string(&report);
    insta::assert_snapshot!(rendered);
}

#[tokio::test]
async fn http_malformed_schema_fails_with_source_span() {
    let tee = FakeRawHttpTee::new();
    let malformed = include_bytes!("fixtures/labeler/http/malformed/first_page.json").to_vec();

    tee.add_response(None, 200, malformed.clone());

    let output = run(&tee).await;

    let mut report = atproto_devtool::commands::test::labeler::report::LabelerReport::new(
        atproto_devtool::commands::test::labeler::report::ReportHeader {
            target: "https://example.com".to_string(),
            resolved_did: None,
            pds_endpoint: None,
            labeler_endpoint: Some("https://example.com".to_string()),
        },
    );

    for result in output.results {
        report.record(result);
    }
    report.finish();

    let rendered = render_report_to_string(&report);
    insta::assert_snapshot!(rendered);
}

#[tokio::test]
async fn http_ignored_cursor_fails() {
    let tee = FakeRawHttpTee::new();
    // Load fixture with identical pages (cursor ignored).
    let first_page =
        include_bytes!("fixtures/labeler/http/ignored_cursor/first_page.json").to_vec();
    let second_page =
        include_bytes!("fixtures/labeler/http/ignored_cursor/second_page.json").to_vec();

    tee.add_response(None, 200, first_page);
    tee.add_response(Some("cursor1"), 200, second_page);

    let output = run(&tee).await;

    let mut report = atproto_devtool::commands::test::labeler::report::LabelerReport::new(
        atproto_devtool::commands::test::labeler::report::ReportHeader {
            target: "https://example.com".to_string(),
            resolved_did: None,
            pds_endpoint: None,
            labeler_endpoint: Some("https://example.com".to_string()),
        },
    );

    for result in output.results {
        report.record(result);
    }
    report.finish();

    let rendered = render_report_to_string(&report);
    insta::assert_snapshot!(rendered);
}

#[tokio::test]
async fn http_transport_error_renders_network_error() {
    let tee = FakeRawHttpTee::new();
    tee.set_transport_error();

    let output = run(&tee).await;

    let mut report = atproto_devtool::commands::test::labeler::report::LabelerReport::new(
        atproto_devtool::commands::test::labeler::report::ReportHeader {
            target: "https://example.com".to_string(),
            resolved_did: None,
            pds_endpoint: None,
            labeler_endpoint: Some("https://example.com".to_string()),
        },
    );

    for result in output.results {
        report.record(result);
    }
    report.finish();

    let rendered = render_report_to_string(&report);
    insta::assert_snapshot!(rendered);
}
