use crate::api::auth::Session;
use crate::error::ApiResult;
use crate::svc::settings_svc::SettingsService;
use rocket::serde::json::Json;
use rocket::serde::{Deserialize, Serialize};
use rocket::State;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PasswordForm {
    pub old_password: String,
    pub new_password: String,
}

#[post("/settings/password", data = "<form>")]
pub async fn change_password(
    session: Session,
    form: Json<PasswordForm>,
    settings: &State<SettingsService>
) -> ApiResult<()> {
    settings.change_password(
        session.uid, &form.old_password, &form.new_password
    ).await
}

#[derive(Deserialize, Debug, Clone)]
pub struct DisplayNameForm {
    pub display_name: Option<String>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct PasswordAnd2faForm {
    pub password: String,
    pub totp_code: Option<String>,
}

#[delete("/settings", data = "<data>")]
pub async fn delete_account(
    session: Session,
    data: Json<PasswordAnd2faForm>,
    settings: &State<SettingsService>
) -> ApiResult<()> {
    settings.delete_account(
        session.uid, &data.password, &data.totp_code
    ).await
}

#[patch("/settings/display_name", data = "<new>")]
pub async fn change_display_name(
    session: Session,
    new: Json<DisplayNameForm>,
    settings: &State<SettingsService>
) -> ApiResult<()> {
    settings.change_display_name(session.uid, new.display_name.clone()).await
}

#[derive(Deserialize)]
pub struct UsernameForm {
    pub username: String,
}

#[patch("/settings/username", data = "<new>")]
pub async fn change_username(
    session: Session,
    new: Json<UsernameForm>,
    settings: &State<SettingsService>
) -> ApiResult<()> {
    settings.change_username(session.uid, &new.username).await
}