use axum::{
    extract::{Path, State},
    http::StatusCode,
    response::Redirect,
    Form,
};
use serde::Deserialize;

use crate::{
    http::error::AppError,
    node::stack::{check_compose, command, commit_compose, write_compose, StackCommand},
    AppState,
};

#[derive(Deserialize)]
pub(super) struct EditStackForm {
    source: String,
    commit_message: String,
}

pub(super) async fn edit_stack(
    Path(stack_name): Path<String>,
    State(state): State<AppState>,
    Form(form): Form<EditStackForm>,
) -> Result<Redirect, AppError> {
    let commit_message = if form.commit_message.trim().is_empty() {
        format!("Update {}", stack_name)
    } else {
        form.commit_message
    };

    if form.source.trim().is_empty() {
        return Err(AppError::Client {
            status: StatusCode::BAD_REQUEST,
            code: "invalid-source",
            message: "provided stack source is empty".to_string(),
        });
    };

    // Cleanup source (like line endings)
    let source = form.source.replace("\r\n", "\n");

    // Make sure file is ok
    check_compose(&state.arion_bin, &source).await?;

    // Write compose file
    write_compose(&state.stack_dir, &stack_name, &source).await?;

    // Git commit
    commit_compose(state.repository, &stack_name, &commit_message)?;

    // Update stack
    command(
        &state.stack_dir,
        &stack_name,
        &state.arion_bin,
        StackCommand::Start,
    )
    .await?;

    Ok(Redirect::to("./"))
}