use sqlx::PgPool;
use uuid::Uuid;

use crate::models::User;

pub async fn find_by_username(pool: &PgPool, username: &str) -> Result<Option<User>, sqlx::Error> {
    sqlx::query_as::<_, User>(
        r#"
        SELECT * FROM users
        WHERE username = $1 AND deleted_at IS NULL
        "#,
    )
    .bind(username)
    .fetch_optional(pool)
    .await
}

pub async fn find_by_email(pool: &PgPool, email: &str) -> Result<Option<User>, sqlx::Error> {
    sqlx::query_as::<_, User>(
        r#"
        SELECT * FROM users
        WHERE email = $1 AND deleted_at IS NULL
        "#,
    )
    .bind(email)
    .fetch_optional(pool)
    .await
}

pub async fn find_by_id(pool: &PgPool, id: Uuid) -> Result<Option<User>, sqlx::Error> {
    sqlx::query_as::<_, User>(
        r#"
        SELECT * FROM users
        WHERE id = $1 AND deleted_at IS NULL
        "#,
    )
    .bind(id)
    .fetch_optional(pool)
    .await
}

pub async fn update_last_login(pool: &PgPool, user_id: Uuid, ip: &str) -> Result<(), sqlx::Error> {
    sqlx::query(
        r#"
        UPDATE users
        SET last_login_at = NOW(), failed_login_attempts = 0
        WHERE id = $1
        "#,
    )
    .bind(user_id)
    .execute(pool)
    .await?;
    Ok(())
}

pub async fn increment_failed_login(pool: &PgPool, username: &str) -> Result<(), sqlx::Error> {
    sqlx::query(
        r#"
        UPDATE users
        SET failed_login_attempts = failed_login_attempts + 1
        WHERE username = $1 AND deleted_at IS NULL
        "#,
    )
    .bind(username)
    .execute(pool)
    .await?;
    Ok(())
}
