use sqlx::PgPool;
use bcrypt::verify;
use crate::{
    db,
    models::{User, LoginRequest, LoginResponse},
    error::{Result, ApiError},
    auth::create_jwt,
};

/// Authentication and user management service
/// Contains all auth-related business logic, keeping handlers thin and focused on HTTP concerns
pub struct AuthService;

impl AuthService {
    /// Authenticate user login
    pub async fn login(pool: &PgPool, request: LoginRequest, jwt_secret: &str) -> Result<LoginResponse> {
        // Get user data directly from database (including password hash)
        let row = sqlx::query!(
            "SELECT id, username, email, name, avatar_url, role, verified, created_at, updated_at, password_hash FROM users WHERE username = $1", 
            request.username
        )
            .fetch_optional(pool)
            .await?;
        
        let user_data = match row {
            Some(row) => row,
            None => return Err(ApiError::AuthError("User not found".to_string())),
        };
        
        // Verify password
        match verify(&request.password, &user_data.password_hash) {
            Ok(true) => {
                // Password is correct - create user with complete data
                let user = User {
                    id: user_data.id,
                    username: user_data.username.clone(),
                    email: user_data.email,
                    name: user_data.name,
                    avatar_url: user_data.avatar_url,
                    role: user_data.role.or_else(|| Some("admin".to_string())),
                    verified: user_data.verified.or_else(|| Some(true)),
                    created_at: user_data.created_at,
                    updated_at: user_data.updated_at,
                };
                
                // Create JWT token
                let token = create_jwt(&user_data.id, &user_data.username, &user.role.as_ref().unwrap_or(&"admin".to_string()), jwt_secret)?;
                
                Ok(LoginResponse { token, user })
            },
            Ok(false) => Err(ApiError::AuthError("Invalid password".to_string())),
            Err(e) => Err(ApiError::AuthError(format!("Bcrypt error: {}", e))),
        }
    }


    /// List all users (admin function)
    pub async fn list_users(pool: &PgPool) -> Result<Vec<User>> {
        db::users::list(pool).await
    }
}