use leptos::prelude::*;

/// Append a navigation event to the JSONL log for this day.
///
/// All visits (anonymous and authenticated) go to
/// `{nav_log_dir}/YYYY-MM-DD.jsonl`. The `user_id` field in the JSON entry is
/// `null` for anonymous visits and the authenticated user UUID for logged-in
/// users, enabling per-user GDPR queries with standard `jq` without splitting
/// traffic across multiple files.
#[server(TrackPageView, "/api")]
pub async fn track_page_view(
    page: String,
    lang: String,
    nav_type: String,
    user_id: Option<String>,
) -> Result<(), ServerFnError> {
    #[cfg(not(target_arch = "wasm32"))]
    {
        use chrono::Utc;
        use tokio::fs;
        use tokio::io::AsyncWriteExt;

        use super::types::{NavLogEntry, NavType};

        let nt = match nav_type.as_str() {
            "spa" => NavType::Spa,
            _ => NavType::Initial,
        };

        let entry = NavLogEntry {
            ts: Utc::now().to_rfc3339(),
            lang,
            page,
            nav_type: nt,
            user_id,
        };

        let line = serde_json::to_string(&entry)
            .map_err(|e| ServerFnError::new(format!("serialization: {e}")))?
            + "\n";

        let base_dir = std::env::var("RUSTELO_NAV_LOG_DIR").unwrap_or_else(|_| {
            let root = std::env::var("SITE_CONTENT_PATH")
                .or_else(|_| std::env::var("PROJECT_ROOT"))
                .unwrap_or_else(|_| ".".to_string());
            format!("{root}/logs/navigation")
        });

        let date_str = Utc::now().format("%Y-%m-%d").to_string();
        let log_path = std::path::PathBuf::from(&base_dir).join(format!("{date_str}.jsonl"));

        if let Some(parent) = log_path.parent() {
            fs::create_dir_all(parent)
                .await
                .map_err(|e| ServerFnError::new(format!("create_dir_all: {e}")))?;
        }

        let mut file = fs::OpenOptions::new()
            .append(true)
            .create(true)
            .open(&log_path)
            .await
            .map_err(|e| ServerFnError::new(format!("open log: {e}")))?;

        file.write_all(line.as_bytes())
            .await
            .map_err(|e| ServerFnError::new(format!("write log: {e}")))?;

        return Ok(());
    }

    #[allow(unreachable_code)]
    Ok(())
}
