use sqlx::PgPool;

use super::dto::{CreateProduct, UpdateProduct};
use super::model::Product;

pub async fn list(pool: &PgPool) -> Result<Vec<Product>, sqlx::Error> {
    sqlx::query_as::<_, Product>("SELECT * FROM products ORDER BY created_at DESC")
        .fetch_all(pool)
        .await
}

pub async fn find(pool: &PgPool, id: uuid::Uuid) -> Result<Product, sqlx::Error> {
    sqlx::query_as::<_, Product>("SELECT * FROM products WHERE id = $1")
        .bind(id)
        .fetch_one(pool)
        .await
}

pub async fn create(pool: &PgPool, input: &CreateProduct) -> Result<Product, sqlx::Error> {
    sqlx::query_as::<_, Product>(
        "INSERT INTO products (name, price, active) VALUES ($1, $2, $3) RETURNING *",
    )
        .bind(input.name.clone())
        .bind(input.price)
        .bind(input.active)
        .fetch_one(pool)
        .await
}

pub async fn update(
    pool: &PgPool,
    id: uuid::Uuid,
    input: &UpdateProduct,
) -> Result<Product, sqlx::Error> {
    sqlx::query_as::<_, Product>(
        "UPDATE products SET name = $1, price = $2, active = $3, updated_at = now() WHERE id = $4 RETURNING *",
    )
        .bind(input.name.clone())
        .bind(input.price)
        .bind(input.active)
        .bind(id)
        .fetch_one(pool)
        .await
}

pub async fn delete(pool: &PgPool, id: uuid::Uuid) -> Result<(), sqlx::Error> {
    let result = sqlx::query("DELETE FROM products WHERE id = $1")
        .bind(id)
        .execute(pool)
        .await?;
    if result.rows_affected() == 0 {
        return Err(sqlx::Error::RowNotFound);
    }
    Ok(())
}
