#![allow(clippy::missing_errors_doc)]
#![allow(clippy::unnecessary_struct_initialization)]
#![allow(clippy::unused_async)]

use axum::http::HeaderMap;
use loco_rs::prelude::*;
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::services::analytics;

#[derive(Clone, Debug, Deserialize)]
pub struct ContentAnalyticsEventPayload {
    pub event_type: String,
    pub path: String,
    #[serde(default)]
    pub post_slug: Option<String>,
    #[serde(default)]
    pub session_id: Option<String>,
    #[serde(default)]
    pub duration_ms: Option<i32>,
    #[serde(default)]
    pub progress_percent: Option<i32>,
    #[serde(default)]
    pub metadata: Option<Value>,
    #[serde(default)]
    pub referrer: Option<String>,
}

#[derive(Clone, Debug, Serialize)]
pub struct ContentAnalyticsEventResponse {
    pub recorded: bool,
}

#[debug_handler]
pub async fn record(
    State(ctx): State<AppContext>,
    headers: HeaderMap,
    Json(payload): Json<ContentAnalyticsEventPayload>,
) -> Result<Response> {
    let mut request_context =
        analytics::content_request_context_from_headers(&payload.path, &headers);
    if payload
        .referrer
        .as_deref()
        .map(str::trim)
        .filter(|value| !value.is_empty())
        .is_some()
    {
        request_context.referrer = payload.referrer;
    }

    analytics::record_content_event(
        &ctx,
        analytics::ContentEventDraft {
            event_type: payload.event_type,
            path: payload.path,
            post_slug: payload.post_slug,
            session_id: payload.session_id,
            request_context,
            duration_ms: payload.duration_ms,
            progress_percent: payload.progress_percent,
            metadata: payload.metadata,
        },
    )
    .await;

    format::json(ContentAnalyticsEventResponse { recorded: true })
}

pub fn routes() -> Routes {
    Routes::new()
        .prefix("api/analytics/")
        .add("content", post(record))
}
