use actix_web::{HttpResponse, Result, web};
use serde::Serialize;
use session::SessionUser;
use utoipa::ToSchema;

use crate::ApiResponse;
use crate::error::ApiError;
use service::AppService;
use service::ws_token::WS_TOKEN_TTL_SECONDS;

#[derive(Debug, Serialize, ToSchema)]
pub struct WsTokenResponse {
    pub token: String,
    pub expires_in_seconds: i64,
}

/// Returns a short-lived token that can be used to authenticate WebSocket connections
/// by passing it as a query parameter: `ws://host/ws?token=xxx`
#[utoipa::path(
    post,
    path = "/api/ws/token",
    responses(
        (status = 200, description = "Token generated successfully", body = ApiResponse<WsTokenResponse>),
        (status = 401, description = "Unauthorized - not logged in", body = ApiResponse<ApiError>),
    ),
    tag = "WebSocket"
)]
pub async fn ws_token_generate(
    service: web::Data<AppService>,
    session_user: SessionUser,
) -> Result<HttpResponse, ApiError> {
    let SessionUser(user_id) = session_user;

    let token = service
        .ws_token
        .generate_token(user_id)
        .await
        .map_err(ApiError::from)?;

    let response = WsTokenResponse {
        token,
        expires_in_seconds: WS_TOKEN_TTL_SECONDS,
    };

    Ok(ApiResponse::ok(response).to_response())
}
