use dropshot::{endpoint, HttpError, HttpResponseOk, Path, RequestContext};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use trace_request::trace_request;
use uuid::Uuid;

use std::sync::Arc;

use crate::context::ControllerContext;

/// User
#[derive(Serialize, JsonSchema)]
struct User {
    id: Uuid,
    name: String,
}

#[allow(dead_code)]
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
struct UsersPathParams {
    user_id: Uuid,
}

/// Fetch user info.
#[endpoint {
    method = GET,
    path = "/users/{userId}",
    tags = [ "user" ],
}]
#[trace_request]
pub(crate) async fn get_user_by_id(
    rqctx: RequestContext<Arc<ControllerContext>>,
    params: Path<UsersPathParams>,
) -> Result<HttpResponseOk<User>, HttpError> {
    let id = params.into_inner().user_id;
    tracing::debug!(id = id.to_string(), "Getting user by id");

    let pg = rqctx.context().pg_pool.to_owned();

    let rec = sqlx::query!(r#"SELECT * FROM users WHERE id = $1"#, id)
        .fetch_one(&pg)
        .await
        .map_err(|e| match e {
            sqlx::Error::RowNotFound => HttpError::for_not_found(None, format!("User not found by id: {:?}", id)),
            err => HttpError::for_internal_error( format!("Error: {}", err))
        }
        )?;

    let user = User {
        id: rec.id,
        name: rec.name,
    };

    Ok(HttpResponseOk(user))
}