//! Campaign history tracking.
//!
//! Maintains the timeline of all events in a campaign with chapter
//! divisions and key moment detection.

use bevy::prelude::*;
use std::collections::HashMap;

use crate::gameplay::narrative::{GameEvent, NarrativeConfig};

/// Complete campaign history with timeline and chapters.
#[derive(Resource, Debug, Clone)]
pub struct CampaignHistory {
    /// All events in chronological order
    pub events: Vec<GameEvent>,
    /// Detected chapters in the campaign
    pub chapters: Vec<Chapter>,
    /// Key moments (significant events)
    pub key_moments: Vec<KeyMoment>,
    /// Campaign statistics
    pub statistics: CampaignStatistics,
    /// Time since last chapter detection
    pub time_since_chapter_check: f32,
}

impl Default for CampaignHistory {
    fn default() -> Self {
        Self {
            events: Vec::new(),
            chapters: Vec::new(),
            key_moments: Vec::new(),
            statistics: CampaignStatistics::default(),
            time_since_chapter_check: 0.0,
        }
    }
}

impl CampaignHistory {
    /// Add a new event to the campaign history.
    pub fn add_event(&mut self, event: GameEvent) {
        // Update statistics before consuming the event
        self.update_statistics(&event);

        // Check if this is a key moment
        if self.is_key_moment(&event) {
            self.key_moments.push(KeyMoment {
                event_index: self.events.len(),
                timestamp: event.timestamp(),
                significance: self.calculate_significance(&event),
                description: event.title(),
            });
        }

        // Finally, consume the event by pushing it to the history
        self.events.push(event);
    }

    /// Get the most recent N events.
    pub fn recent_events(&self, count: usize) -> &[GameEvent] {
        let start = self.events.len().saturating_sub(count);
        &self.events[start..]
    }

    /// Get all events since a given timestamp.
    pub fn events_since(&self, timestamp: f64) -> &[GameEvent] {
        let start = self
            .events
            .partition_point(|e| e.timestamp() < timestamp);
        &self.events[start..]
    }

    /// Check if an event is a key moment.
    fn is_key_moment(&self, event: &GameEvent) -> bool {
        match event {
            GameEvent::Combat(e) => {
                matches!(e.outcome, crate::gameplay::narrative::CombatOutcome::Victory)
                    && e.hull_remaining < 0.3
            }
            GameEvent::Exploration(e) => {
                matches!(
                    e.discovery_type,
                    crate::gameplay::narrative::DiscoveryType::NewSystem
                )
            }
            GameEvent::Mission(e) => {
                matches!(
                    e.event_type,
                    crate::gameplay::narrative::MissionEventType::Completed
                )
            }
            _ => false,
        }
    }

    /// Calculate the significance score of an event (0.0 to 1.0).
    fn calculate_significance(&self, event: &GameEvent) -> f32 {
        match event {
            GameEvent::Combat(e) => {
                let base = 0.7;
                let bonus = if e.hull_remaining < 0.3 { 0.2 } else { 0.0 };
                base + bonus
            }
            GameEvent::Exploration(_) => 0.6,
            GameEvent::Mission(_) => 0.5,
            GameEvent::Trade(_) => 0.2,
            GameEvent::Mining(_) => 0.1,
            GameEvent::Docking(_) => 0.05,
            GameEvent::Custom(_) => 0.4,
        }
    }

    /// Update campaign statistics based on a new event.
    fn update_statistics(&mut self, event: &GameEvent) {
        match event {
            GameEvent::Mining(_) => self.statistics.mining_operations += 1,
            GameEvent::Trade(_) => self.statistics.trade_operations += 1,
            GameEvent::Combat(e) => {
                self.statistics.combat_operations += 1;
                match e.outcome {
                    crate::gameplay::narrative::CombatOutcome::Victory => {
                        self.statistics.combat_victories += 1
                    }
                    crate::gameplay::narrative::CombatOutcome::Defeat => {
                        self.statistics.combat_defeats += 1
                    }
                    _ => {}
                }
            }
            GameEvent::Exploration(_) => self.statistics.discoveries += 1,
            GameEvent::Mission(_) => self.statistics.missions_completed += 1,
            GameEvent::Docking(_) => self.statistics.docking_operations += 1,
            GameEvent::Custom(_) => {}
        }
    }
}

/// A chapter in the campaign narrative.
#[derive(Debug, Clone)]
pub struct Chapter {
    /// Chapter index (0-based)
    pub index: usize,
    /// Chapter title
    pub title: String,
    /// Start event index
    pub start_event: usize,
    /// End event index (exclusive)
    pub end_event: usize,
    /// Primary theme of this chapter
    pub theme: ChapterTheme,
    /// Summary of events in this chapter
    pub summary: String,
    /// Timestamp when chapter started
    pub start_timestamp: f64,
}

/// Themes that chapters can have.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChapterTheme {
    Exploration,
    Commerce,
    Conflict,
    Diplomacy,
    Mystery,
    Survival,
    Growth,
}

/// A key moment in the campaign.
#[derive(Debug, Clone)]
pub struct KeyMoment {
    /// Index of the event in the campaign history
    pub event_index: usize,
    /// When this occurred
    pub timestamp: f64,
    /// How significant (0.0 to 1.0)
    pub significance: f32,
    /// Description
    pub description: String,
}

/// Campaign statistics.
#[derive(Debug, Clone, Default)]
pub struct CampaignStatistics {
    /// Total events logged
    pub total_events: usize,
    /// Mining operations performed
    pub mining_operations: u32,
    /// Trade operations performed
    pub trade_operations: u32,
    /// Combat operations performed
    pub combat_operations: u32,
    /// Combat victories
    pub combat_victories: u32,
    /// Combat defeats
    pub combat_defeats: u32,
    /// Discoveries made
    pub discoveries: u32,
    /// Missions completed
    pub missions_completed: u32,
    /// Docking operations
    pub docking_operations: u32,
}

/// Detect chapters in the campaign history.
///
/// This system runs periodically and analyzes the event stream to
/// identify natural chapter boundaries based on event patterns.
pub fn detect_chapters(
    mut history: ResMut<CampaignHistory>,
    config: Res<NarrativeConfig>,
    time: Res<Time>,
) {
    history.time_since_chapter_check += time.delta_secs();

    // Only check every 10 seconds
    if history.time_since_chapter_check < 10.0 {
        return;
    }

    history.time_since_chapter_check = 0.0;

    // Only detect chapters if we have enough events
    if history.events.len() < config.events_per_chapter {
        return;
    }

    // Calculate expected chapter count
    let expected_chapters = history.events.len() / config.events_per_chapter;

    // Add new chapter if needed
    if history.chapters.len() < expected_chapters {
        let start_index = if let Some(last_chapter) = history.chapters.last() {
            last_chapter.end_event
        } else {
            0
        };

        let end_index = (start_index + config.events_per_chapter).min(history.events.len());

        // Determine theme from events in this range
        let theme = detect_chapter_theme(&history.events[start_index..end_index]);

        let chapter = Chapter {
            index: history.chapters.len(),
            title: format!("Chapter {}: {:?}", history.chapters.len() + 1, theme),
            start_event: start_index,
            end_event: end_index,
            theme,
            summary: generate_chapter_summary(&history.events[start_index..end_index]),
            start_timestamp: history
                .events
                .get(start_index)
                .map(|e| e.timestamp())
                .unwrap_or(0.0),
        };

        bevy::log::info!("Detected new chapter: {}", chapter.title);
        history.chapters.push(chapter);
    }
}

/// Detect the theme of a chapter from its events.
fn detect_chapter_theme(events: &[GameEvent]) -> ChapterTheme {
    let mut counts = HashMap::new();

    for event in events {
        let category = match event {
            GameEvent::Mining(_) => "commerce",
            GameEvent::Trade(_) => "commerce",
            GameEvent::Combat(_) => "conflict",
            GameEvent::Exploration(_) => "exploration",
            GameEvent::Docking(_) => "commerce",
            GameEvent::Mission(_) => "growth",
            GameEvent::Custom(_) => "mystery",
        };

        *counts.entry(category).or_insert(0) += 1;
    }

    let max_category = counts
        .into_iter()
        .max_by_key(|(_, count)| *count)
        .map(|(cat, _)| cat)
        .unwrap_or("exploration");

    match max_category {
        "exploration" => ChapterTheme::Exploration,
        "commerce" => ChapterTheme::Commerce,
        "conflict" => ChapterTheme::Conflict,
        "growth" => ChapterTheme::Growth,
        "mystery" => ChapterTheme::Mystery,
        _ => ChapterTheme::Exploration,
    }
}

/// Generate a summary for a chapter from its events.
fn generate_chapter_summary(events: &[GameEvent]) -> String {
    if events.is_empty() {
        return "Empty chapter".to_string();
    }

    let start = events.first().unwrap();
    let end = events.last().unwrap();

    let duration_hours = (end.timestamp() - start.timestamp()) / 3600.0;

    format!(
        "Events from {:.1} hours of gameplay. Started with {}, ended with {}.",
        duration_hours,
        start.title(),
        end.title()
    )
}
