use serde::Deserialize;
use std::sync::Arc;

use axum::extract::{Path, State};
use axum::http::StatusCode;
use axum::http::{HeaderValue, header};
use axum::response::IntoResponse;

pub async fn get(
    State(state): State<Arc<crate::server::AppState>>,
    Path(path): Path<String>,
) -> impl IntoResponse {
    get_asset_to_res(state, path)
}

#[allow(clippy::needless_pass_by_value)]
pub fn get_asset_to_res(state: Arc<crate::server::AppState>, path: String) -> impl IntoResponse {
    let span = tracing::info_span!("assets");

    span.in_scope(|| {
        let span = tracing::info_span!("storage");

        span.in_scope(|| {
            if let Ok(asset) = state.storage.get_asset(&path) {
                if let Ok(reader) = flexbuffers::Reader::get_root(&asset[..])
                    && let Ok(crate::server::Asset(mime, content)) =
                        crate::server::Asset::deserialize(reader)
                    && let Ok(mime) = HeaderValue::from_str(&mime)
                {
                    return (
                        StatusCode::OK,
                        [(header::CONTENT_TYPE, mime)],
                        bytes::Bytes::copy_from_slice(&content[..]),
                    );
                }

                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    [(
                        header::CONTENT_TYPE,
                        HeaderValue::from_static(mime::TEXT_HTML_UTF_8.as_ref()),
                    )],
                    bytes::Bytes::new(),
                )
            } else {
                (
                    StatusCode::NOT_FOUND,
                    [(
                        header::CONTENT_TYPE,
                        HeaderValue::from_static(mime::TEXT_HTML_UTF_8.as_ref()),
                    )],
                    bytes::Bytes::new(),
                )
            }
        })
    })
}
