use httpmock::Method::GET;
use httpmock::MockServer;
use std::time::Duration;
use url::Url;
use yfinance_rs::{
    HistoryBuilder, YfClient, YfError,
    core::client::{Backoff, RetryConfig},
};

#[tokio::test]
async fn history_retries_on_persistent_5xx() {
    let server = MockServer::start();
    let sym = "RETRY";

    // This single mock will persistently fail, allowing us to count the retries.
    let fail_mock = server.mock(|when, then| {
        when.method(GET)
            .path(format!("/v8/finance/chart/{sym}"))
            .query_param("range", "6mo")
            .query_param("interval", "1d")
            .query_param("events", "div|split|capitalGains")
            .query_param("includePrePost", "false");
        then.status(503).body("Service Unavailable");
    });

    let max_retries = 3;
    let client_retry_config = RetryConfig {
        backoff: Backoff::Fixed(Duration::from_millis(1)),
        max_retries,
        ..RetryConfig::default()
    };

    let client = YfClient::builder()
        .base_chart(Url::parse(&format!("{}/v8/finance/chart/", server.base_url())).unwrap())
        .retry_config(client_retry_config)
        .build()
        .unwrap();

    // We expect this to fail, so we match on the Err variant.
    let result = HistoryBuilder::new(&client, sym).fetch().await;

    // The mock should be hit 1 (initial) + 3 (retries) = 4 times.
    fail_mock.assert_calls((1 + max_retries) as usize);

    // Assert that the final result is the expected error.
    match result {
        Err(YfError::ServerError { status, .. }) => {
            assert_eq!(status, 503);
        }
        other => panic!("Expected a ServerError after all retries failed, got {other:?}"),
    }
}
