use load_rs::Body::{Data, DataFile};
use load_rs::{HttpMethod, LoadTestRunner, Order, Stats};
use reqwest::header::HeaderMap;
use std::path::Path;

mod common;

#[tokio::test]
async fn debug_get() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/get", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let response = runner.debug(HttpMethod::Get, None, None).await.unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_head() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/get", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let response = runner.debug(HttpMethod::Head, None, None).await.unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_post() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/post", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let mut headers = HeaderMap::new();
    headers.insert("Content-Type", "application/json".parse().unwrap());
    let response = runner
        .debug(
            HttpMethod::Post,
            Some(headers),
            Some(Data("{\"message\": \"hello\"}".into())),
        )
        .await
        .unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_put() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/put", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let mut headers = HeaderMap::new();
    headers.insert("Content-Type", "application/json".parse().unwrap());
    let response = runner
        .debug(
            HttpMethod::Put,
            Some(headers),
            Some(Data("{\"message\": \"hello\"}".into())),
        )
        .await
        .unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_patch() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/patch", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let mut headers = HeaderMap::new();
    headers.insert("Content-Type", "application/json".parse().unwrap());
    let response = runner
        .debug(
            HttpMethod::Patch,
            Some(headers),
            Some(Data("{\"message\": \"hello\"}".into())),
        )
        .await
        .unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_delete() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/delete", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let mut headers = HeaderMap::new();
    headers.insert("Content-Type", "application/json".parse().unwrap());
    let response = runner
        .debug(
            HttpMethod::Delete,
            Some(headers),
            Some(Data("{\"message\": \"hello\"}".into())),
        )
        .await
        .unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_from_data_file() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/post", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let mut headers = HeaderMap::new();
    headers.insert("Content-Type", "application/json".parse().unwrap());
    let response = runner
        .debug(
            HttpMethod::Post,
            Some(headers),
            Some(DataFile("tests/test_requests/test1.json".into())),
        )
        .await
        .unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_from_dir_sequential() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/post", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let mut headers = HeaderMap::new();
    headers.insert("Content-Type", "application/json".parse().unwrap());
    let response = runner
        .debug_from_dir(
            HttpMethod::Post,
            Some(headers),
            Path::new("tests/test_requests"),
            Order::Sequential,
        )
        .await
        .unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_from_dir_random() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/post", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let mut headers = HeaderMap::new();
    headers.insert("Content-Type", "application/json".parse().unwrap());
    let response = runner
        .debug_from_dir(
            HttpMethod::Post,
            Some(headers),
            Path::new("tests/test_requests"),
            Order::Random,
        )
        .await
        .unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_from_manifest_sequential() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/post", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let response = runner
        .debug_from_manifest(
            HttpMethod::Post,
            Path::new("tests/test_manifests/requests.jsonl"),
            Order::Sequential,
        )
        .await
        .unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn debug_from_manifest_random() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/post", 5, 2)
        .stats(Stats::Success)
        .build()
        .await
        .unwrap();

    let response = runner
        .debug_from_manifest(
            HttpMethod::Post,
            Path::new("tests/test_manifests/requests.jsonl"),
            Order::Random,
        )
        .await
        .unwrap();

    assert_eq!(response.status(), 200);
}

#[tokio::test]
async fn test_user_agent() {
    let runner = LoadTestRunner::builder("https://mockhttp.org/get", 1, 1)
        .stats(Stats::All)
        .user_agent("custom-agent/1.0")
        .build()
        .await
        .unwrap();

    let resp = runner.debug(HttpMethod::Get, None, None).await.unwrap();

    let body = resp.text().await.unwrap();
    assert!(body.contains("\"user-agent\":\"custom-agent/1.0\""));
}

#[tokio::test]
async fn debug_mtls_valid_certs() {
    let test_server = common::run_server(common::HttpVersion::Http1)
        .await
        .unwrap();

    let runner = LoadTestRunner::builder(format!("https://{}", test_server.addr), 1, 1)
        .stats(Stats::Success)
        .ca_cert("tests/tls/ca.crt")
        .cert("tests/tls/client.crt")
        .key("tests/tls/client.key")
        .build()
        .await
        .unwrap();

    let response = runner.debug(HttpMethod::Get, None, None).await.unwrap();

    assert_eq!(response.status(), 200);
}
