//! Factory functions for the `User` struct from `doctate_server::config`.
//!
//! Tests previously copy-pasted a 10-line `make_user` in every file.
//! These factories centralise the defaults (doctor role, bcrypt cost 4,
//! window 72 h, password "s") so an API change to `User` touches one
//! file, not twenty.

use doctate_server::config::{RetentionUserSettings, User};

/// Bcrypt cost factor used in all tests. The production default is 12;
/// tests drop it to 4 because the hash is computed on every `test_user()`
/// call and a cost-12 hash adds ~200 ms per test. Security is irrelevant
/// for test-only passwords; speed is not.
pub const TEST_BCRYPT_COST: u32 = 4;

/// Default plaintext password across tests. Individual tests that need
/// a specific password (e.g. for a login-wrong-password assertion) use
/// [`test_user_with_password`] instead.
pub const TEST_PASSWORD: &str = "s";

/// Bcrypt-hash the test password. Extracted so the cost factor lives in
/// one place.
fn hash_password(plain: &str) -> String {
    bcrypt::hash(plain, TEST_BCRYPT_COST).unwrap()
}

/// Doctor user. `api_key = "key-{slug}"` — kept deterministic so tests
/// that send the X-API-Key header can compute it from the slug without
/// keeping a separate constant.
pub fn test_user(slug: &str) -> User {
    User {
        slug: slug.into(),
        api_key: format!("key-{slug}"),
        web_password: hash_password(TEST_PASSWORD),
        role: "doctor".into(),
        language: None,
        retention: Default::default(),
        window_hours: 72,
        preview_lines: 2,
    }
}

/// Admin variant — used by bulk/reset/purge-closed tests where the
/// handler enforces `role == "admin"`.
pub fn test_admin(slug: &str) -> User {
    let mut u = test_user(slug);
    u.role = "admin".into();
    u
}

/// Doctor user with an explicit plaintext password. Used by tests that
/// log in with a specific password (e.g. wrong-password rejection).
pub fn test_user_with_password(slug: &str, password: &str) -> User {
    let mut u = test_user(slug);
    u.web_password = hash_password(password);
    u
}

/// Doctor user with custom retention settings — for the retention sweep
/// tests that drive the lazy auto-close / auto-purge logic.
pub fn test_user_with_retention(slug: &str, auto_close_days: u32, auto_delete_days: u32) -> User {
    let mut u = test_user(slug);
    u.retention = RetentionUserSettings {
        auto_close_days,
        auto_delete_days,
    };
    u
}

/// Doctor user with a custom `window_hours` — used by `/api/oneliners`
/// tests that verify the visibility window is server-authoritative.
pub fn test_user_with_window_hours(slug: &str, hours: u32) -> User {
    let mut u = test_user(slug);
    u.window_hours = hours;
    u
}
