//! `POST /api/record?type={new|part|tail|remove}&file=&offset=&length=`
//!
//! No Authorization header — clients fire-and-forget. The wire flow is
//! defined in CONSOLE_API.md §8 and src/hbbs_http/record_upload.rs in the
//! client. We dispatch on `?type=` into the storage state machine.

pub mod storage;

use crate::api::error::ApiError;
use crate::api::state::AppState;
use axum::body::Bytes;
use axum::extract::{Extension, Query};
use axum::http::StatusCode;
use serde::Deserialize;
use std::sync::Arc;

#[derive(Debug, Deserialize)]
pub struct RecordQuery {
    #[serde(rename = "type")]
    pub kind: String,
    pub file: String,
    #[serde(default)]
    pub offset: Option<u64>,
    #[serde(default)]
    pub length: Option<usize>,
}

pub async fn record(
    Extension(state): Extension<Arc<AppState>>,
    Query(q): Query<RecordQuery>,
    body: Bytes,
) -> Result<StatusCode, ApiError> {
    match q.kind.as_str() {
        "new" => storage::handle_new(&state, &q.file, "").await?,
        "part" => {
            let offset = q.offset.unwrap_or(0);
            let length = q.length.unwrap_or(body.len());
            storage::handle_part(&state, &q.file, offset, length, &body).await?;
        }
        "tail" => {
            let offset = q.offset.unwrap_or(0);
            let length = q.length.unwrap_or(body.len());
            storage::handle_tail(&state, &q.file, offset, length, &body).await?;
        }
        "remove" => storage::handle_remove(&state, &q.file).await?,
        other => {
            return Err(ApiError::BadRequest(format!(
                "unknown record type {:?}",
                other
            )));
        }
    }
    Ok(StatusCode::OK)
}
