use cfg_if::cfg_if;

cfg_if! {
if #[cfg(feature = "ssr")] {
    use axum::{
        body::{boxed, Body, BoxBody},
        http::{Request, Response, StatusCode, Uri},
    };
    use tower::ServiceExt;
    use tower_http::services::ServeDir;

    pub async fn file_handler(uri: Uri) -> Result<Response<BoxBody>, (StatusCode, String)> {
        let res = get_static_file(uri.clone(), "/pkg").await?;

        if res.status() == StatusCode::NOT_FOUND {
            // try with `.html`
            // TODO: handle if the Uri has query parameters
            match format!("{}.html", uri).parse() {
                Ok(uri_html) => get_static_file(uri_html, "/pkg").await,
                Err(_) => Err((StatusCode::INTERNAL_SERVER_ERROR, "Invalid URI".to_string())),
            }
        } else {
            Ok(res)
        }
    }

    pub async fn get_static_file_handler(uri: Uri) -> Result<Response<BoxBody>, (StatusCode, String)> {
        let res = get_static_file(uri.clone(), "/static").await?;

        if res.status() == StatusCode::NOT_FOUND {
          Err((StatusCode::INTERNAL_SERVER_ERROR, "Invalid URI".to_string()))
        } else {
            Ok(res)
        }
    }

    async fn get_static_file(uri: Uri, base: &str) -> Result<Response<BoxBody>, (StatusCode, String)> {
        let req = Request::builder().uri(&uri).body(Body::empty()).unwrap();

        // `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot`
        // When run normally, the root should be the crate root
        if base == "/static" {
            match ServeDir::new("./static").oneshot(req).await {
                Ok(res) => Ok(res.map(boxed)),
                Err(err) => Err((
                    StatusCode::INTERNAL_SERVER_ERROR,
                    format!("Something went wrong: {}", err),
                ))
        }
        } else if base == "/pkg" {
            match ServeDir::new("./pkg").oneshot(req).await {
                Ok(res) => Ok(res.map(boxed)),
                Err(err) => Err((
                    StatusCode::INTERNAL_SERVER_ERROR,
                    format!("Something went wrong: {}", err),
                )),
        }
    } else{
           Err((StatusCode::NOT_FOUND, "Not Found".to_string()))
        }
    }
    }
}
