#![cfg(feature = "miltertest-tests")]

mod common;

pub use crate::common::*;
use byte_strings::c_str;
use indymilter::{Callbacks, ContextActions, Status};
use tracing::info;

#[tokio::test]
async fn basic_stages() {
    init_tracing_subscriber();

    let callbacks = Callbacks::<()>::new()
        .on_negotiate(|_, actions, opts| {
            Box::pin(async move {
                info!(?actions, ?opts, "inside negotiate callback");
                Status::AllOpts
            })
        })
        .on_connect(|_, hostname, socket_info| {
            Box::pin(async move {
                info!(?hostname, ?socket_info, "inside connect callback");
                Status::Continue
            })
        })
        .on_helo(|_, hostname| {
            Box::pin(async move {
                info!(?hostname, "inside helo callback");
                Status::Continue
            })
        })
        .on_eom(|cx| {
            Box::pin(async move {
                info!("inside eom callback");

                cx.actions.add_header("name1", "value1").await.unwrap();
                cx.actions.add_header("name2", "value2").await.unwrap();

                Status::Continue
            })
        })
        .on_close(|_| {
            Box::pin(async move {
                info!("inside close callback");
                Status::Continue
            })
        });

    let milter = Milter::spawn(LOCALHOST, callbacks, default_config())
        .await
        .unwrap();

    let addr = milter.addr();

    let exit_code = run_miltertest("mt_basic.lua", addr).await.unwrap();

    milter.shutdown().await.unwrap();

    assert!(exit_code.success());
}

#[tokio::test]
async fn eoh_eom_macros() {
    init_tracing_subscriber();

    let callbacks = Callbacks::<()>::new()
        .on_eoh(|_| Box::pin(async { Status::Continue }))
        .on_eom(|cx| {
            Box::pin(async move {
                // Make sure `eoh`/`eom` macros are stored in the right order.
                if let Some(name) = cx.macros.get(c_str!("{name}")) {
                    if name.to_string_lossy() == "5678" {
                        return Status::Continue;
                    }
                }
                Status::Tempfail
            })
        });

    let milter = Milter::spawn(LOCALHOST, callbacks, default_config())
        .await
        .unwrap();

    let addr = milter.addr();

    let exit_code = run_miltertest("mt_macros.lua", addr).await.unwrap();

    milter.shutdown().await.unwrap();

    assert!(exit_code.success());
}
