//! rok-auth — JWT authentication and RBAC for the rok ecosystem.
//!
//! ```rust,no_run
//! use rok_auth::{Auth, AuthConfig, Claims};
//!
//! let auth = Auth::new(AuthConfig {
//!     secret: "super-secret-key".to_string(),
//!     ..Default::default()
//! });
//!
//! // Sign a token
//! let token = auth.sign(&Claims::new("user-123", vec!["admin"])).unwrap();
//!
//! // Verify and decode
//! let claims = auth.verify(&token).unwrap();
//! assert_eq!(claims.sub, "user-123");
//! assert!(claims.has_role("admin"));
//! ```

pub mod access_token;
pub mod api_key;
pub mod blacklist;
pub mod claims;
pub mod config;
pub mod email_verification;
pub mod error;
pub mod hash;
pub mod jwt;
pub mod macros;
pub mod password;
pub mod password_reset;
pub mod policy;
pub mod provider;
pub mod session;
pub mod token_pair;
pub mod totp;

/// Magic-link passwordless authentication.  Enable with `features = ["magic-link"]`.
#[cfg(feature = "magic-link")]
pub mod magic_link;

/// WebAuthn / passkey authentication.  Enable with `features = ["passkeys"]`.
#[cfg(feature = "passkeys")]
pub mod passkey;

/// Device trust — remember this device to bypass TOTP.  Enable with `features = ["device-trust"]`.
#[cfg(feature = "device-trust")]
pub mod device_trust;

pub use blacklist::TokenBlacklist;
pub use claims::{Claims, RefreshClaims};
pub use config::AuthConfig;
pub use email_verification::EmailVerification;
pub use error::AuthError;
pub use jwt::Auth;
pub use password_reset::PasswordReset;
pub use policy::Policy;
pub use provider::UserProvider;
pub use session::SessionToken;
pub use token_pair::TokenPair;

#[cfg(feature = "magic-link")]
pub use magic_link::{MagicLink, MagicLinkConfig};

#[cfg(feature = "device-trust")]
pub use device_trust::{DeviceTrust, DeviceTrustConfig, TrustDevice};

/// Axum extractors, middleware, and `IntoResponse` impl for [`AuthError`].
///
/// Enable with `features = ["axum"]`.
#[cfg(feature = "axum")]
pub mod axum;

// ── migration set ─────────────────────────────────────────────────────────────

use rok_orm_migrate::{EmbeddedMigration, EmbeddedMigrations};

static MIGRATIONS: &[EmbeddedMigration] = &[
    EmbeddedMigration {
        name: "001_personal_access_tokens",
        up:   include_str!("../migrations/001_personal_access_tokens.sql"),
        down: "DROP TABLE IF EXISTS personal_access_tokens;",
    },
    EmbeddedMigration {
        name: "002_token_blacklist",
        up:   include_str!("../migrations/002_token_blacklist.sql"),
        down: "DROP TABLE IF EXISTS token_blacklist;",
    },
    EmbeddedMigration {
        name: "003_email_verification",
        up:   include_str!("../migrations/003_email_verification.sql"),
        down: "DROP TABLE IF EXISTS email_verification_tokens; ALTER TABLE users DROP COLUMN IF EXISTS email_verified_at;",
    },
    EmbeddedMigration {
        name: "004_password_resets",
        up:   include_str!("../migrations/004_password_resets.sql"),
        down: "DROP TABLE IF EXISTS password_resets;",
    },
    EmbeddedMigration {
        name: "005_totp",
        up:   include_str!("../migrations/005_totp.sql"),
        down: "ALTER TABLE users DROP COLUMN IF EXISTS totp_secret; ALTER TABLE users DROP COLUMN IF EXISTS totp_enabled;",
    },
    EmbeddedMigration {
        name: "006_passkey_credentials",
        up:   include_str!("../migrations/006_passkey_credentials.sql"),
        down: "DROP TABLE IF EXISTS passkey_credentials;",
    },
    EmbeddedMigration {
        name: "007_device_trust_tokens",
        up:   include_str!("../migrations/007_device_trust_tokens.sql"),
        down: "DROP TABLE IF EXISTS device_trust_tokens;",
    },
];

/// Returns the embedded migrations required by rok-auth.
///
/// Register this with [`rok_orm_migrate::MigrationRunner`] before running your
/// app.  All tables owned by rok-auth (e.g. `personal_access_tokens`) will be
/// created in the correct order.
///
/// # Example
///
/// ```rust,ignore
/// MigrationRunner::new(pool)
///     .source(rok_auth::migrations())
///     .source(FileSource::new("./migrations"))
///     .run()
///     .await?;
/// ```
pub fn migrations() -> EmbeddedMigrations {
    EmbeddedMigrations::new(MIGRATIONS)
}
