//! User Interaction Tracker
//!
//! Tracks and analyzes user interactions including:
//! - Click events and navigation patterns
//! - Form interactions and submissions
//! - Scroll behavior and engagement
//! - Time on page and session duration

use super::super::{AnalyticsEvent, EventLevel, LogSource, generate_event_id};
use super::InteractionEvent;
use anyhow::Result;
use chrono::{DateTime, Duration, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tokio::sync::mpsc;

/// Interaction types
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum InteractionType {
    Click,
    DoubleClick,
    RightClick,
    FormSubmit,
    FormFocus,
    FormBlur,
    Scroll,
    KeyPress,
    MouseEnter,
    MouseLeave,
    PageView,
    PageExit,
}

/// User session information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserSession {
    pub session_id: String,
    pub start_time: DateTime<Utc>,
    pub last_activity: DateTime<Utc>,
    pub page_views: u32,
    pub interactions: u32,
    pub total_scroll_depth: f64,
    pub current_page: String,
}

/// Interaction pattern analysis
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InteractionPattern {
    /// Most clicked elements
    pub popular_elements: Vec<(String, u64)>,
    /// Common navigation paths
    pub navigation_paths: Vec<(String, String, u64)>, // from, to, count
    /// Average time on page by URL
    pub time_on_page: HashMap<String, f64>,
    /// Form completion rates
    pub form_completion_rates: HashMap<String, f64>,
    /// Scroll behavior analysis
    pub scroll_patterns: ScrollAnalysis,
}

/// Scroll behavior analysis
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScrollAnalysis {
    /// Average scroll depth percentage
    pub avg_scroll_depth: f64,
    /// Pages with high scroll depth (>80%)
    pub high_engagement_pages: Vec<String>,
    /// Pages with low scroll depth (<20%)
    pub low_engagement_pages: Vec<String>,
    /// Scroll speed patterns
    pub scroll_speed_analysis: String,
}

/// Interaction statistics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InteractionStats {
    pub total_interactions: u64,
    pub unique_sessions: u64,
    pub avg_session_duration_ms: u64,
    pub avg_interactions_per_session: f64,
    pub bounce_rate: f64, // percentage of single-page sessions
    pub popular_pages: Vec<(String, u64)>,
    pub interaction_types: HashMap<String, u64>,
}

impl Default for InteractionStats {
    fn default() -> Self {
        Self {
            total_interactions: 0,
            unique_sessions: 0,
            avg_session_duration_ms: 0,
            avg_interactions_per_session: 0.0,
            bounce_rate: 0.0,
            popular_pages: Vec::new(),
            interaction_types: HashMap::new(),
        }
    }
}

/// User interaction tracker
pub struct InteractionTracker {
    sessions: HashMap<String, UserSession>,
    monitoring_interval: u64,
}

impl InteractionTracker {
    /// Create new interaction tracker
    pub fn new() -> Self {
        Self {
            sessions: HashMap::new(),
            monitoring_interval: 20, // 20 seconds
        }
    }

    /// Start interaction monitoring
    pub async fn start_monitoring(&mut self, sender: mpsc::UnboundedSender<AnalyticsEvent>) -> Result<()> {
        tracing::info!("Starting user interaction tracking...");

        let interval = self.monitoring_interval;

        tokio::spawn(async move {
            let mut interval_timer = tokio::time::interval(
                tokio::time::Duration::from_secs(interval)
            );

            loop {
                interval_timer.tick().await;

                // Simulate interaction collection
                // In a real implementation, this would:
                // - Receive events from browser via WebSocket
                // - Process click tracking data
                // - Analyze form interactions
                // - Track page navigation

                if let Ok(interactions) = Self::collect_interactions().await {
                    for interaction in interactions {
                        let event = Self::create_interaction_event(interaction);

                        if let Err(e) = sender.send(event) {
                            tracing::error!("Failed to send interaction event: {}", e);
                            break;
                        }
                    }
                }

                // Generate session analytics
                if let Ok(session_event) = Self::generate_session_analytics().await {
                    if let Err(e) = sender.send(session_event) {
                        tracing::error!("Failed to send session analytics: {}", e);
                        break;
                    }
                }
            }
        });

        tracing::info!("Interaction tracking started");
        Ok(())
    }

    /// Collect user interactions (simulated)
    async fn collect_interactions() -> Result<Vec<SimulatedInteraction>> {
        let mut interactions = Vec::new();

        // Simulate various user interactions
        if rand::random::<f64>() < 0.6 { // 60% chance of interactions
            let interaction_scenarios = vec![
                SimulatedInteraction {
                    interaction_type: InteractionType::Click,
                    element_id: Some("nav-home".to_string()),
                    element_class: Some("nav-link".to_string()),
                    element_tag: "a".to_string(),
                    page_url: "/".to_string(),
                    coordinates: Some((120, 45)),
                    timestamp: Utc::now(),
                    session_id: "session_123".to_string(),
                },
                SimulatedInteraction {
                    interaction_type: InteractionType::FormSubmit,
                    element_id: Some("contact-form".to_string()),
                    element_class: Some("form".to_string()),
                    element_tag: "form".to_string(),
                    page_url: "/contact".to_string(),
                    coordinates: None,
                    timestamp: Utc::now(),
                    session_id: "session_456".to_string(),
                },
                SimulatedInteraction {
                    interaction_type: InteractionType::Scroll,
                    element_id: None,
                    element_class: None,
                    element_tag: "body".to_string(),
                    page_url: "/blog/post-1".to_string(),
                    coordinates: Some((0, 800)),
                    timestamp: Utc::now(),
                    session_id: "session_789".to_string(),
                },
                SimulatedInteraction {
                    interaction_type: InteractionType::PageView,
                    element_id: None,
                    element_class: None,
                    element_tag: "html".to_string(),
                    page_url: "/recipes".to_string(),
                    coordinates: None,
                    timestamp: Utc::now(),
                    session_id: "session_101".to_string(),
                },
            ];

            let selected = &interaction_scenarios[rand::random::<usize>() % interaction_scenarios.len()];
            interactions.push(selected.clone());
        }

        Ok(interactions)
    }

    /// Generate session analytics
    async fn generate_session_analytics() -> Result<AnalyticsEvent> {
        // Simulate session analysis
        let stats = InteractionStats {
            total_interactions: 1250 + rand::random::<u64>() % 500,
            unique_sessions: 85 + rand::random::<u64>() % 50,
            avg_session_duration_ms: 120000 + rand::random::<u64>() % 180000,
            avg_interactions_per_session: 8.5 + rand::random::<f64>() * 5.0,
            bounce_rate: 0.35 + rand::random::<f64>() * 0.2,
            popular_pages: vec![
                ("/".to_string(), 450),
                ("/recipes".to_string(), 320),
                ("/blog".to_string(), 280),
            ],
            interaction_types: {
                let mut types = HashMap::new();
                types.insert("Click".to_string(), 650);
                types.insert("PageView".to_string(), 230);
                types.insert("Scroll".to_string(), 180);
                types.insert("FormSubmit".to_string(), 45);
                types
            },
        };

        let mut metadata = HashMap::new();
        metadata.insert("total_interactions".to_string(),
            serde_json::Value::Number(stats.total_interactions.into()));
        metadata.insert("unique_sessions".to_string(),
            serde_json::Value::Number(stats.unique_sessions.into()));
        metadata.insert("avg_session_duration_ms".to_string(),
            serde_json::Value::Number(stats.avg_session_duration_ms.into()));
        metadata.insert("avg_interactions_per_session".to_string(),
            serde_json::Value::Number(serde_json::Number::from_f64(stats.avg_interactions_per_session).unwrap()));
        metadata.insert("bounce_rate".to_string(),
            serde_json::Value::Number(serde_json::Number::from_f64(stats.bounce_rate).unwrap()));

        let message = format!(
            "Session Analytics: {} interactions, {} sessions, {:.1}% bounce rate",
            stats.total_interactions,
            stats.unique_sessions,
            stats.bounce_rate * 100.0
        );

        Ok(AnalyticsEvent {
            id: generate_event_id(),
            timestamp: Utc::now(),
            source: LogSource::Browser,
            event_type: "user_interaction_analytics".to_string(),
            session_id: None,
            path: None,
            level: EventLevel::Info,
            message,
            metadata,
            duration_ms: Some(stats.avg_session_duration_ms),
            errors: Vec::new(),
        })
    }

    /// Create analytics event from interaction
    fn create_interaction_event(interaction: SimulatedInteraction) -> AnalyticsEvent {
        let mut metadata = HashMap::new();
        metadata.insert("interaction_type".to_string(),
            serde_json::Value::String(format!("{:?}", interaction.interaction_type)));
        metadata.insert("element_tag".to_string(),
            serde_json::Value::String(interaction.element_tag.clone()));
        metadata.insert("session_id".to_string(),
            serde_json::Value::String(interaction.session_id.clone()));

        if let Some(id) = &interaction.element_id {
            metadata.insert("element_id".to_string(), serde_json::Value::String(id.clone()));
        }

        if let Some(class) = &interaction.element_class {
            metadata.insert("element_class".to_string(), serde_json::Value::String(class.clone()));
        }

        if let Some((x, y)) = interaction.coordinates {
            metadata.insert("coordinates".to_string(),
                serde_json::Value::Array(vec![
                    serde_json::Value::Number(x.into()),
                    serde_json::Value::Number(y.into()),
                ]));
        }

        let event_type = match interaction.interaction_type {
            InteractionType::Click | InteractionType::DoubleClick | InteractionType::RightClick => "user_click",
            InteractionType::FormSubmit | InteractionType::FormFocus | InteractionType::FormBlur => "form_interaction",
            InteractionType::Scroll => "scroll_event",
            InteractionType::PageView | InteractionType::PageExit => "navigation_event",
            _ => "user_interaction",
        }.to_string();

        let message = match interaction.interaction_type {
            InteractionType::Click => {
                format!("User clicked {} on {}",
                    interaction.element_id.as_deref().unwrap_or("element"),
                    interaction.page_url)
            }
            InteractionType::FormSubmit => {
                format!("Form submitted: {} on {}",
                    interaction.element_id.as_deref().unwrap_or("form"),
                    interaction.page_url)
            }
            InteractionType::PageView => {
                format!("Page viewed: {}", interaction.page_url)
            }
            InteractionType::Scroll => {
                format!("User scrolled on {}", interaction.page_url)
            }
            _ => {
                format!("User interaction: {:?} on {}",
                    interaction.interaction_type,
                    interaction.page_url)
            }
        };

        AnalyticsEvent {
            id: generate_event_id(),
            timestamp: interaction.timestamp,
            source: LogSource::Browser,
            event_type,
            session_id: Some(interaction.session_id),
            path: Some(interaction.page_url),
            level: EventLevel::Info,
            message,
            metadata,
            duration_ms: None,
            errors: Vec::new(),
        }
    }

    /// Analyze interaction patterns
    pub async fn analyze_interaction_patterns(&self) -> Result<InteractionPattern> {
        // Simulate pattern analysis
        let popular_elements = vec![
            ("nav-home".to_string(), 245),
            ("contact-form".to_string(), 89),
            ("blog-link".to_string(), 156),
            ("recipe-card".to_string(), 203),
        ];

        let navigation_paths = vec![
            ("/".to_string(), "/recipes".to_string(), 89),
            ("/recipes".to_string(), "/recipes/rust".to_string(), 45),
            ("/".to_string(), "/blog".to_string(), 67),
            ("/blog".to_string(), "/".to_string(), 34),
        ];

        let mut time_on_page = HashMap::new();
        time_on_page.insert("/".to_string(), 45.2);
        time_on_page.insert("/recipes".to_string(), 120.5);
        time_on_page.insert("/blog".to_string(), 95.8);
        time_on_page.insert("/contact".to_string(), 180.0);

        let mut form_completion_rates = HashMap::new();
        form_completion_rates.insert("contact-form".to_string(), 0.78);
        form_completion_rates.insert("newsletter-signup".to_string(), 0.45);
        form_completion_rates.insert("feedback-form".to_string(), 0.62);

        let scroll_patterns = ScrollAnalysis {
            avg_scroll_depth: 68.5,
            high_engagement_pages: vec![
                "/blog/rust-tutorial".to_string(),
                "/recipes/docker".to_string(),
            ],
            low_engagement_pages: vec![
                "/legal".to_string(),
                "/privacy".to_string(),
            ],
            scroll_speed_analysis: "Users scroll 15% slower on blog posts, indicating higher engagement".to_string(),
        };

        Ok(InteractionPattern {
            popular_elements,
            navigation_paths,
            time_on_page,
            form_completion_rates,
            scroll_patterns,
        })
    }

    /// Generate interaction analysis report
    pub async fn generate_interaction_report(&self) -> Result<String> {
        let patterns = self.analyze_interaction_patterns().await?;

        let mut report = String::from("👥 User Interaction Analysis\n\n");

        report.push_str("🖱️ Popular Elements:\n");
        for (element, clicks) in patterns.popular_elements.iter().take(5) {
            report.push_str(&format!("  {}: {} clicks\n", element, clicks));
        }

        report.push_str("\n🧭 Navigation Patterns:\n");
        for (from, to, count) in patterns.navigation_paths.iter().take(3) {
            report.push_str(&format!("  {} → {}: {} transitions\n", from, to, count));
        }

        report.push_str("\n⏱️ Time on Page:\n");
        for (page, time) in patterns.time_on_page.iter() {
            report.push_str(&format!("  {}: {:.1}s average\n", page, time));
        }

        report.push_str("\n📝 Form Completion Rates:\n");
        for (form, rate) in patterns.form_completion_rates.iter() {
            report.push_str(&format!("  {}: {:.1}%\n", form, rate * 100.0));
        }

        report.push_str(&format!("\n📜 Scroll Analysis:\n"));
        report.push_str(&format!("  Average Scroll Depth: {:.1}%\n", patterns.scroll_patterns.avg_scroll_depth));
        report.push_str(&format!("  High Engagement Pages: {}\n", patterns.scroll_patterns.high_engagement_pages.len()));
        report.push_str(&format!("  Low Engagement Pages: {}\n", patterns.scroll_patterns.low_engagement_pages.len()));

        Ok(report)
    }
}

/// Simulated interaction for testing
#[derive(Debug, Clone)]
pub struct SimulatedInteraction {
    pub interaction_type: InteractionType,
    pub element_id: Option<String>,
    pub element_class: Option<String>,
    pub element_tag: String,
    pub page_url: String,
    pub coordinates: Option<(i32, i32)>,
    pub timestamp: DateTime<Utc>,
    pub session_id: String,
}
