use ntex::http::header::{CONTENT_LENGTH, CONTENT_TYPE};
use ntex::{
    http::Response,
    web::{self, HttpRequest, error},
};

use crate::util::requester::Requester;

const REFERER: &str = "https://fikfap.com/";

fn endpoint_to_image_url(req: &HttpRequest) -> String {
    let endpoint = req.match_info().query("endpoint").trim_start_matches('/');
    let mut image_url = if endpoint.starts_with("http://") || endpoint.starts_with("https://") {
        endpoint.to_string()
    } else {
        format!("https://{endpoint}")
    };

    let query = req.query_string();
    if !query.is_empty() && !image_url.contains('?') {
        image_url.push('?');
        image_url.push_str(query);
    }

    image_url
}

pub async fn get_image(
    req: HttpRequest,
    requester: web::types::State<Requester>,
) -> Result<impl web::Responder, web::Error> {
    let image_url = endpoint_to_image_url(&req);

    let upstream = match requester
        .get_ref()
        .clone()
        .get_raw_with_headers(
            image_url.as_str(),
            vec![("Referer".to_string(), REFERER.to_string())],
        )
        .await
    {
        Ok(response) => response,
        Err(_) => return Ok(web::HttpResponse::NotFound().finish()),
    };

    let status = upstream.status();
    let headers = upstream.headers().clone();
    let bytes = upstream.bytes().await.map_err(error::ErrorBadGateway)?;

    let mut resp = Response::build(status);

    if let Some(ct) = headers.get(CONTENT_TYPE) {
        if let Ok(ct_str) = ct.to_str() {
            resp.set_header(CONTENT_TYPE, ct_str);
        }
    }
    if let Some(cl) = headers.get(CONTENT_LENGTH) {
        if let Ok(cl_str) = cl.to_str() {
            resp.set_header(CONTENT_LENGTH, cl_str);
        }
    }

    Ok(resp.body(bytes.to_vec()))
}
