// Copyright (c) 2026, Salesforce, Inc.,
// All rights reserved.
// For full license text, see the LICENSE.txt file

use anyhow::Result;
use pdk_test::port::PortVisibility;
use serde_json::{json, Value};

use pdk_test::services::httpbin::{HttpBin, HttpBinConfig};
use pdk_test::{pdk_test, TestComposite, TestError};

#[pdk_test]
async fn httpbin() -> Result<()> {
    let composite = TestComposite::builder()
        .with_service(
            HttpBinConfig::builder()
                .visibility(PortVisibility::Published)
                .build(),
        )
        .build()
        .await?;

    let httpbin: HttpBin = composite.service()?;

    let response = reqwest::get(format!("{}/get", httpbin.address().unwrap())).await?;

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

    let mut actual = response.json::<Value>().await?;
    actual.as_object_mut().unwrap().remove("origin");

    let expected_host = httpbin.socket().map(|s| s.trim_end_matches(":80")).unwrap();

    let expected_url = httpbin
        .address()
        .map(|s| format!("{}/get", s.trim_end_matches(":80")))
        .unwrap();

    assert_eq!(
        actual,
        json! ({
            "args": {},
            "headers": {
                "Accept": "*/*",
                "Host": expected_host,
            },
            "url": expected_url,
        })
    );

    Ok(())
}

#[pdk_test]
async fn invalid_explicit_repository() {
    let httpbin_config = HttpBinConfig::builder()
        .image_name("unknown/httpmock")
        .build();

    let result = TestComposite::builder()
        .with_service(httpbin_config)
        .build()
        .await;

    assert!(result.is_err());

    let Err(error) = result else {
        unreachable!();
    };

    assert!(matches!(error, TestError::Docker(_)));
}

#[pdk_test]
async fn valid_explicit_image_name() {
    let httpbin_config = HttpBinConfig::builder()
        .image_name("kennethreitz/httpbin")
        .build();

    let result = TestComposite::builder()
        .with_service(httpbin_config)
        .build()
        .await;

    assert!(result.is_ok());
}
