use axum::{
    Extension, Json,
    extract::{Path, State},
};
use serde::Deserialize;
use serde_json::{Value, json};

use crate::{
    auth::AuthenticatedSession,
    error::ApiError,
    service::{RotateSecretPayload, SecretPayload},
    state::AppState,
};

#[derive(Deserialize)]
pub struct WorkspacePath {
    pub workspace_id: String,
}

#[derive(Deserialize)]
pub struct WorkspaceSecretPath {
    pub workspace_id: String,
    pub secret_id: String,
}

pub async fn list_secrets(
    Path(path): Path<WorkspacePath>,
    State(state): State<AppState>,
) -> Result<Json<Value>, ApiError> {
    let items = state
        .service
        .list_secrets(&path.workspace_id.as_str().into())
        .await?;
    Ok(Json(json!({ "items": items })))
}

pub async fn create_secret(
    Path(path): Path<WorkspacePath>,
    State(state): State<AppState>,
    Extension(session): Extension<AuthenticatedSession>,
    Json(payload): Json<SecretPayload>,
) -> Result<Json<Value>, ApiError> {
    let secret = state
        .service
        .create_secret(
            &path.workspace_id.as_str().into(),
            Some(&session.user.id),
            payload,
        )
        .await?;
    Ok(Json(json!(secret)))
}

pub async fn get_secret(
    Path(path): Path<WorkspaceSecretPath>,
    State(state): State<AppState>,
) -> Result<Json<Value>, ApiError> {
    let secret = state
        .service
        .get_secret(
            &path.workspace_id.as_str().into(),
            &path.secret_id.as_str().into(),
        )
        .await?;
    Ok(Json(json!(secret)))
}

pub async fn rotate_secret(
    Path(path): Path<WorkspaceSecretPath>,
    State(state): State<AppState>,
    Extension(session): Extension<AuthenticatedSession>,
    Json(payload): Json<RotateSecretPayload>,
) -> Result<Json<Value>, ApiError> {
    let secret = state
        .service
        .rotate_secret(
            &path.workspace_id.as_str().into(),
            &path.secret_id.as_str().into(),
            Some(&session.user.id),
            payload,
        )
        .await?;
    Ok(Json(json!(secret)))
}

pub async fn delete_secret(
    Path(path): Path<WorkspaceSecretPath>,
    State(state): State<AppState>,
) -> Result<Json<Value>, ApiError> {
    state
        .service
        .delete_secret(
            &path.workspace_id.as_str().into(),
            &path.secret_id.as_str().into(),
        )
        .await?;
    Ok(Json(json!({ "ok": true })))
}
