use actix_web::{HttpMessage, HttpRequest};

#[derive(Debug, Clone)]
pub struct ResolvedAthenaClient(pub String);

#[derive(Debug, Clone)]
pub struct ResolvedAthenaClientSource {
    pub source: String,
    pub outcome: String,
    pub wildcard_host_pattern: Option<String>,
    pub matched_host: Option<String>,
    pub wildcard_prefix: Option<String>,
    pub route_key: Option<String>,
    pub tenant_ref: Option<String>,
    pub service_key: Option<String>,
    pub major_version: Option<String>,
}

#[derive(Debug, Clone)]
pub struct ResolvedAthenaRouteTargetUrl(pub String);

#[derive(Debug, Clone, Copy)]
pub struct DisallowJdbcRouting;

#[derive(Debug, Clone)]
pub struct AthenaRequestId(pub String);

#[derive(Debug, Clone)]
pub struct AthenaRequestTraceId(pub String);

/// Sets the resolved Athena client name in request extensions.
pub fn set_resolved_athena_client(req: &HttpRequest, client_name: String) {
    req.extensions_mut()
        .insert(ResolvedAthenaClient(client_name));
}

/// Retrieves the resolved Athena client name from request extensions.
pub fn resolved_athena_client(req: &HttpRequest) -> Option<String> {
    req.extensions()
        .get::<ResolvedAthenaClient>()
        .map(|value| value.0.clone())
}

/// Sets metadata describing how the Athena client was resolved.
pub fn set_resolved_athena_client_source(req: &HttpRequest, source: ResolvedAthenaClientSource) {
    req.extensions_mut().insert(source);
}

/// Retrieves metadata describing how the Athena client was resolved.
pub fn resolved_athena_client_source(req: &HttpRequest) -> Option<ResolvedAthenaClientSource> {
    req.extensions()
        .get::<ResolvedAthenaClientSource>()
        .cloned()
}

/// Sets the resolved public route target URL in request extensions.
pub fn set_resolved_athena_route_target_url(req: &HttpRequest, target_url: String) {
    req.extensions_mut()
        .insert(ResolvedAthenaRouteTargetUrl(target_url));
}

/// Retrieves the resolved public route target URL from request extensions.
pub fn resolved_athena_route_target_url(req: &HttpRequest) -> Option<String> {
    req.extensions()
        .get::<ResolvedAthenaRouteTargetUrl>()
        .map(|value| value.0.clone())
}

/// Marks the request as ineligible for direct JDBC routing.
pub fn set_disallow_jdbc_routing(req: &HttpRequest) {
    req.extensions_mut().insert(DisallowJdbcRouting);
}

/// Returns whether direct JDBC routing was disabled in request extensions.
pub fn disallow_jdbc_routing(req: &HttpRequest) -> bool {
    req.extensions().get::<DisallowJdbcRouting>().is_some()
}

/// Sets the per-request Athena request identifier in request extensions.
pub fn set_athena_request_id(req: &HttpRequest, request_id: String) {
    req.extensions_mut().insert(AthenaRequestId(request_id));
}

/// Retrieves the per-request Athena request identifier from request extensions.
pub fn athena_request_id(req: &HttpRequest) -> Option<String> {
    req.extensions()
        .get::<AthenaRequestId>()
        .map(|value| value.0.clone())
}

/// Sets the per-request Athena trace identifier in request extensions.
pub fn set_athena_request_trace_id(req: &HttpRequest, trace_id: String) {
    req.extensions_mut().insert(AthenaRequestTraceId(trace_id));
}

/// Retrieves the per-request Athena trace identifier from request extensions.
pub fn athena_request_trace_id(req: &HttpRequest) -> Option<String> {
    req.extensions()
        .get::<AthenaRequestTraceId>()
        .map(|value| value.0.clone())
}
