use db::Db;
use domain::Role;
use sqlx::PgPool;

// Note: `server::create_user` opens its own DB connection by URL, but `#[sqlx::test]`
// provisions a temporary database whose URL is not directly exposed. The test below
// exercises the same building blocks that `server::create_user` composes —
// `auth::hash_password` + `db::users::create_user` + `db::users::credentials_by_email` —
// against the test pool, which fully validates the end-to-end bootstrap logic.

#[sqlx::test(migrations = "../db/migrations")]
async fn create_user_persists_and_password_verifies(pool: PgPool) {
    let db = Db::from_pool(pool.clone());

    let hash = auth::hash_password("bootstrap-pw-123").unwrap();

    let mut tx = db.pool().begin().await.unwrap();

    db::users::create_user(
        &mut tx,
        domain::AuditActor::System,
        &domain::NewUser {
            email: domain::Email::parse("boss@example.com").unwrap(),
            password_hash: hash,
            role: Role::Admin,
        },
    )
    .await
    .unwrap();

    tx.commit().await.unwrap();

    let (user, stored_hash) = db::users::credentials_by_email(db.pool(), "boss@example.com")
        .await
        .unwrap()
        .unwrap();

    assert_eq!(user.role, Role::Admin);
    assert!(auth::verify_password("bootstrap-pw-123", &stored_hash));
}

#[tokio::test]
async fn create_user_rejects_invalid_email() {
    // The email is parsed before the password is read or the DB is touched, so an
    // invalid email errors out without reaching the (unreachable) database URL.
    let err = server::create_user("postgres://unused", "not-an-email", Role::Admin)
        .await
        .unwrap_err();
    assert!(err.to_string().contains("email"), "got: {err}");
}
