use std::sync::Arc;

use axum::extract::Query;
use axum::http::{header, StatusCode};
use axum::response::IntoResponse;

use crate::state::AppState;

#[derive(serde::Deserialize)]
pub struct OgImageQuery {
    #[serde(rename = "v")]
    view: Option<String>,
    #[serde(rename = "f")]
    filters: Option<String>,
    poi: Option<String>,
    tab: Option<String>,
}

pub async fn get_og_image(
    state: Arc<AppState>,
    Query(query): Query<OgImageQuery>,
) -> impl IntoResponse {
    let sidecar_url = match &state.og_sidecar_url {
        Some(url) => url,
        None => {
            return (StatusCode::SERVICE_UNAVAILABLE, "OG sidecar not configured").into_response();
        }
    };

    let mut params = Vec::new();
    if let Some(ref val) = query.view {
        params.push(format!("v={}", urlencoding::encode(val)));
    }
    if let Some(ref val) = query.filters {
        params.push(format!("f={}", urlencoding::encode(val)));
    }
    if let Some(ref val) = query.poi {
        params.push(format!("poi={}", urlencoding::encode(val)));
    }
    if let Some(ref val) = query.tab {
        params.push(format!("tab={}", urlencoding::encode(val)));
    }

    let qs = if params.is_empty() {
        String::new()
    } else {
        format!("?{}", params.join("&"))
    };

    let url = format!("{}/screenshot{}", sidecar_url, qs);
    tracing::info!("Proxying OG screenshot request to: {}", url);

    match state.http_client.get(&url).send().await {
        Ok(resp) if resp.status().is_success() => match resp.bytes().await {
            Ok(bytes) => (
                StatusCode::OK,
                [
                    (header::CONTENT_TYPE, "image/png"),
                    (header::CACHE_CONTROL, "public, max-age=86400"),
                ],
                bytes,
            )
                .into_response(),
            Err(err) => {
                tracing::warn!("Failed to read sidecar response: {}", err);
                (StatusCode::BAD_GATEWAY, "Failed to read screenshot").into_response()
            }
        },
        Ok(resp) => {
            let status = resp.status();
            let body = resp.text().await.unwrap_or_default();
            tracing::warn!("Sidecar returned status {}: {}", status, body);
            (StatusCode::BAD_GATEWAY, "Screenshot sidecar error").into_response()
        }
        Err(err) => {
            tracing::warn!("Failed to reach sidecar: {}", err);
            (StatusCode::BAD_GATEWAY, "Screenshot sidecar unavailable").into_response()
        }
    }
}
