use crate::{DateTimeUtc, UserId};
use sea_orm::JsonValue;
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};

/// Auth action types: login, logout, register, password_change, password_reset, 2fa_enabled, etc.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum AuthAction {
    Login,
    Logout,
    Register,
    PasswordChange,
    PasswordReset,
    TwoFactorEnabled,
    TwoFactorDisabled,
    TwoFactorBackupCodesRegenerated,
}

impl std::fmt::Display for AuthAction {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            AuthAction::Login => write!(f, "login"),
            AuthAction::Logout => write!(f, "logout"),
            AuthAction::Register => write!(f, "register"),
            AuthAction::PasswordChange => write!(f, "password_change"),
            AuthAction::PasswordReset => write!(f, "password_reset"),
            AuthAction::TwoFactorEnabled => write!(f, "2fa_enabled"),
            AuthAction::TwoFactorDisabled => write!(f, "2fa_disabled"),
            AuthAction::TwoFactorBackupCodesRegenerated => {
                write!(f, "2fa_backup_codes_regenerated")
            }
        }
    }
}

impl std::str::FromStr for AuthAction {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "login" => Ok(AuthAction::Login),
            "logout" => Ok(AuthAction::Logout),
            "register" => Ok(AuthAction::Register),
            "password_change" => Ok(AuthAction::PasswordChange),
            "password_reset" => Ok(AuthAction::PasswordReset),
            "2fa_enabled" => Ok(AuthAction::TwoFactorEnabled),
            "2fa_disabled" => Ok(AuthAction::TwoFactorDisabled),
            "2fa_backup_codes_regenerated" => Ok(AuthAction::TwoFactorBackupCodesRegenerated),
            _ => Err("unknown auth action"),
        }
    }
}

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "user_activity_log")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i64,
    pub user_uid: Option<UserId>,
    pub action: String,
    pub ip_address: Option<String>,
    pub user_agent: Option<String>,
    pub details: JsonValue,
    pub created_at: DateTimeUtc,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

impl ActiveModelBehavior for ActiveModel {}
