use actix_web::{http::header, web, HttpRequest, HttpResponse};
use mime_guess2::MimeGuess;

fn cache_control_header(path: &str) -> &'static str {
    if path == "index.html" {
        "no-cache, no-store, must-revalidate"
    } else if path.ends_with(".js")
        || path.ends_with(".css")
        || path.ends_with(".woff2")
        || path.ends_with(".woff")
        || path.ends_with(".ttf")
        || path.ends_with(".otf")
        || path.ends_with(".png")
        || path.ends_with(".jpg")
        || path.ends_with(".jpeg")
        || path.ends_with(".gif")
        || path.ends_with(".svg")
        || path.ends_with(".ico")
        || path.ends_with(".webp")
        || path.ends_with(".avif")
        || path.ends_with(".map")
    {
        "public, max-age=31536000, immutable"
    } else {
        "no-cache"
    }
}

pub async fn serve_frontend(req: HttpRequest, path: web::Path<String>) -> HttpResponse {
    let path = path.into_inner();
    let path_str = if path.is_empty() || path == "/" {
        "index.html"
    } else {
        path.as_str()
    };

    let cc = cache_control_header(path_str);

    match frontend::get_frontend_asset_with_etag(path_str) {
        Some((data, etag)) => {
            // Check If-None-Match for conditional request
            if let Some(if_none_match) = req.headers().get(header::IF_NONE_MATCH) {
                if let Ok(client_etag) = if_none_match.to_str() {
                    if client_etag == etag {
                        return HttpResponse::NotModified()
                            .insert_header(("Cache-Control", cc))
                            .insert_header(("ETag", etag))
                            .finish();
                    }
                }
            }

            let mime = MimeGuess::from_path(path_str).first_or_octet_stream();
            HttpResponse::Ok()
                .content_type(mime.as_ref())
                .insert_header(("Cache-Control", cc))
                .insert_header(("ETag", etag))
                .body(data.to_vec())
        }
        None => match frontend::get_frontend_asset_with_etag("index.html") {
            Some((data, etag)) => HttpResponse::Ok()
                .content_type("text/html")
                .insert_header(("Cache-Control", "no-cache, no-store, must-revalidate"))
                .insert_header(("ETag", etag))
                .body(data.to_vec()),
            None => HttpResponse::NotFound().finish(),
        },
    }
}
