use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use uuid::Uuid;

/// 时间轮任务
#[derive(Clone, Debug)]
pub struct TimerTask {
    pub id: Uuid,
    pub notification_id: Uuid,
    pub trigger_at: i64, // Unix timestamp in seconds
}

/// 单层时间轮
struct WheelLevel {
    slots: Vec<Vec<TimerTask>>,
    current: usize,
    slot_count: usize,
    interval_secs: i64, // 每个槽位代表的秒数
}

impl WheelLevel {
    fn new(slot_count: usize, interval_secs: i64) -> Self {
        let slots = (0..slot_count).map(|_| Vec::new()).collect();
        Self {
            slots,
            current: 0,
            slot_count,
            interval_secs,
        }
    }

    /// 将任务添加到指定槽位
    fn add_to_slot(&mut self, slot: usize, task: TimerTask) {
        self.slots[slot].push(task);
    }

    /// 获取当前槽位的所有任务并清空
    fn take_current(&mut self) -> Vec<TimerTask> {
        std::mem::take(&mut self.slots[self.current])
    }

    /// 移动到下一个槽位，返回是否完成一圈
    fn advance(&mut self) -> bool {
        self.current = (self.current + 1) % self.slot_count;
        self.current == 0
    }
}

/// 多级时间轮
///
/// 结构：
/// - Level 0: 秒轮 (60 slots, 每槽 1 秒)
/// - Level 1: 分钟轮 (60 slots, 每槽 60 秒)
/// - Level 2: 小时轮 (24 slots, 每槽 3600 秒)
/// - Level 3: 天轮 (30 slots, 每槽 86400 秒)
pub struct TimeWheel {
    levels: Vec<WheelLevel>,
    current_time: i64,               // 当前时间
    task_index: HashMap<Uuid, Uuid>, // task_id -> notification_id 用于取消任务
}

impl TimeWheel {
    pub fn new() -> Self {
        let now = chrono::Utc::now().timestamp();
        Self {
            levels: vec![
                WheelLevel::new(60, 1),     // 秒轮: 60槽, 每槽1秒
                WheelLevel::new(60, 60),    // 分钟轮: 60槽, 每槽60秒
                WheelLevel::new(24, 3600),  // 小时轮: 24槽, 每槽1小时
                WheelLevel::new(30, 86400), // 天轮: 30槽, 每槽1天
            ],
            current_time: now,
            task_index: HashMap::new(),
        }
    }

    /// 计算任务应该放入哪一层的哪个槽位
    ///
    /// 时间轮结构：
    /// - Level 0 (秒轮): 60 slots, interval=1s, 覆盖 1-60s 的延迟
    /// - Level 1 (分钟轮): 60 slots, interval=60s, 覆盖 60s-1h 的延迟
    /// - Level 2 (小时轮): 24 slots, interval=3600s, 覆盖 1h-24h 的延迟
    /// - Level 3 (天轮): 30 slots, interval=86400s, 覆盖 1d-30d 的延迟
    ///
    /// 级联逻辑：当 Level N 完成一圈时，从 Level N+1 的当前槽取出任务降级
    fn calculate_slot(&self, trigger_at: i64) -> Option<(usize, usize)> {
        let delay = trigger_at - self.current_time;
        if delay <= 0 {
            // 已经过期，放入秒轮当前槽位（立即执行）
            return Some((0, self.levels[0].current));
        }

        // 计算每个层级的总覆盖范围
        let mut level_ranges: Vec<i64> = Vec::new();
        let mut cumulative = 0i64;
        for level in &self.levels {
            cumulative += level.slot_count as i64 * level.interval_secs;
            level_ranges.push(cumulative);
        }

        // 找到合适的层级
        let mut prev_range = 0i64;
        for (level_idx, &range) in level_ranges.iter().enumerate() {
            if delay <= range {
                let level = &self.levels[level_idx];

                // 计算槽位偏移
                // 对于秒轮：delay=5 -> slot 5 (从当前位置偏移5)
                // 对于高层级轮：需要考虑何时会级联
                let slots_away = if level_idx == 0 {
                    delay as usize
                } else {
                    // 高层级轮中，任务会在 (slots_away * lower_level_total_ticks) 后级联
                    // 我们需要找到最小的 slots_away 使得 (slots_away * lower_level_total_ticks) >= delay
                    // 但不能太大，否则会延迟太久
                    //
                    // 例如：delay=65, lower_level_range=60
                    // 我们希望在 tick 60 时级联（slots_away=0），然后剩余 5 秒在 L0 处理
                    //
                    // 公式：slots_away = (delay - prev_range - 1) / lower_level_range
                    // delay=65, prev_range=60: (65-60-1)/60 = 0 -> 在当前槽级联
                    // delay=120, prev_range=60: (120-60-1)/60 = 0 -> 在当前槽级联
                    // delay=121, prev_range=60: (121-60-1)/60 = 1 -> 在下一槽级联

                    // 实际上更简单：我们计算从当前槽开始，需要多少个槽位
                    // delay 落在 (prev_range, range] 区间
                    // 每个槽位覆盖 level.interval_secs 秒
                    // 从当前槽开始，slot[0] 在下一次级联时处理，覆盖 (prev_range, prev_range + interval]
                    // slot[1] 覆盖 (prev_range + interval, prev_range + 2*interval]
                    //
                    // slots_away = (delay - prev_range - 1) / interval
                    ((delay - prev_range - 1) / level.interval_secs) as usize
                };

                let target_slot = (level.current + slots_away) % level.slot_count;
                return Some((level_idx, target_slot));
            }
            prev_range = range;
        }

        // 超过最大范围，放入最高层级的最后一个槽位
        let last_level = self.levels.len() - 1;
        Some((
            last_level,
            (self.levels[last_level].current + self.levels[last_level].slot_count - 1)
                % self.levels[last_level].slot_count,
        ))
    }

    /// 添加定时任务
    pub fn add_task(&mut self, task: TimerTask) -> bool {
        if let Some((level, slot)) = self.calculate_slot(task.trigger_at) {
            self.task_index.insert(task.id, task.notification_id);
            self.levels[level].add_to_slot(slot, task);
            true
        } else {
            false
        }
    }

    /// 取消任务（标记删除，实际在 tick 时过滤）
    pub fn cancel_task(&mut self, task_id: Uuid) -> bool {
        self.task_index.remove(&task_id).is_some()
    }

    /// 检查任务是否有效（未被取消）
    fn is_task_valid(&self, task: &TimerTask) -> bool {
        self.task_index.contains_key(&task.id)
    }

    /// 时间轮前进一秒
    /// 返回需要执行的任务列表
    pub fn tick(&mut self) -> Vec<TimerTask> {
        // 先移动到下一个槽位
        let cascade = self.levels[0].advance();
        self.current_time += 1;

        let mut ready_tasks = Vec::new();

        // 级联处理高层级时间轮（在获取当前槽任务之前）
        if cascade {
            self.cascade_from_level(1);
        }

        // 从秒轮获取当前槽位的任务
        let tasks = self.levels[0].take_current();
        for task in tasks {
            if self.is_task_valid(&task) {
                if task.trigger_at <= self.current_time {
                    // 任务已到期，加入执行队列
                    self.task_index.remove(&task.id);
                    ready_tasks.push(task);
                } else {
                    // 重新计算槽位（理论上不应该发生）
                    if let Some((level, slot)) = self.calculate_slot(task.trigger_at) {
                        self.levels[level].add_to_slot(slot, task);
                    }
                }
            }
        }

        ready_tasks
    }

    /// 从指定层级开始级联处理
    fn cascade_from_level(&mut self, start_level: usize) {
        if start_level >= self.levels.len() {
            return;
        }

        // 从高层级轮取出当前槽位的任务，降级到低层级
        let tasks = self.levels[start_level].take_current();
        for task in tasks {
            if self.is_task_valid(&task) {
                // 重新计算槽位，降级到更低层级
                if let Some((new_level, slot)) = self.calculate_slot(task.trigger_at) {
                    self.levels[new_level].add_to_slot(slot, task);
                }
            }
        }

        // 高层级轮前进
        let cascade = self.levels[start_level].advance();
        if cascade {
            self.cascade_from_level(start_level + 1);
        }
    }

    /// 获取时间轮状态统计
    pub fn stats(&self) -> TimeWheelStats {
        let mut total_tasks = 0;
        let mut level_counts = Vec::new();

        for level in &self.levels {
            let count: usize = level.slots.iter().map(|s| s.len()).sum();
            level_counts.push(count);
            total_tasks += count;
        }

        TimeWheelStats {
            total_tasks,
            level_counts,
            current_time: self.current_time,
        }
    }
}

impl Default for TimeWheel {
    fn default() -> Self {
        Self::new()
    }
}

#[derive(Debug, Clone)]
pub struct TimeWheelStats {
    pub total_tasks: usize,
    pub level_counts: Vec<usize>,
    pub current_time: i64,
}

/// 线程安全的时间轮包装
pub struct SharedTimeWheel {
    inner: Arc<RwLock<TimeWheel>>,
}

impl SharedTimeWheel {
    pub fn new() -> Self {
        Self {
            inner: Arc::new(RwLock::new(TimeWheel::new())),
        }
    }

    pub async fn add_task(&self, task: TimerTask) -> bool {
        let mut wheel = self.inner.write().await;
        wheel.add_task(task)
    }

    pub async fn cancel_task(&self, task_id: Uuid) -> bool {
        let mut wheel = self.inner.write().await;
        wheel.cancel_task(task_id)
    }

    pub async fn tick(&self) -> Vec<TimerTask> {
        let mut wheel = self.inner.write().await;
        wheel.tick()
    }

    pub async fn stats(&self) -> TimeWheelStats {
        let wheel = self.inner.read().await;
        wheel.stats()
    }
}

impl Default for SharedTimeWheel {
    fn default() -> Self {
        Self::new()
    }
}

impl Clone for SharedTimeWheel {
    fn clone(&self) -> Self {
        Self {
            inner: Arc::clone(&self.inner),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_add_task_immediate() {
        let mut wheel = TimeWheel::new();
        let now = wheel.current_time;

        let task = TimerTask {
            id: Uuid::new_v4(),
            notification_id: Uuid::new_v4(),
            trigger_at: now + 5, // 5秒后
        };

        assert!(wheel.add_task(task));
        assert_eq!(wheel.stats().total_tasks, 1);
    }

    #[test]
    fn test_tick_executes_task() {
        let mut wheel = TimeWheel::new();
        let now = wheel.current_time;

        let task = TimerTask {
            id: Uuid::new_v4(),
            notification_id: Uuid::new_v4(),
            trigger_at: now + 1, // 1秒后
        };

        wheel.add_task(task.clone());

        // 前进1秒
        let tasks = wheel.tick();
        assert_eq!(tasks.len(), 1);
        assert_eq!(tasks[0].notification_id, task.notification_id);
    }

    #[test]
    fn test_cascade_from_minute_level() {
        let mut wheel = TimeWheel::new();
        let now = wheel.current_time;

        let task = TimerTask {
            id: Uuid::new_v4(),
            notification_id: Uuid::new_v4(),
            trigger_at: now + 65, // 65秒后，应该放入分钟轮
        };

        wheel.add_task(task.clone());

        // 分钟轮应该有任务
        assert!(wheel.stats().level_counts[1] > 0 || wheel.stats().level_counts[0] > 0);

        // 前进65秒
        let mut executed = Vec::new();
        for _ in 0..66 {
            executed.extend(wheel.tick());
        }

        assert_eq!(executed.len(), 1);
        assert_eq!(executed[0].notification_id, task.notification_id);
    }

    #[test]
    fn test_cancel_task() {
        let mut wheel = TimeWheel::new();
        let now = wheel.current_time;

        let task = TimerTask {
            id: Uuid::new_v4(),
            notification_id: Uuid::new_v4(),
            trigger_at: now + 5,
        };

        wheel.add_task(task.clone());
        assert!(wheel.cancel_task(task.id));

        // 前进5秒，任务不应执行
        let mut executed = Vec::new();
        for _ in 0..6 {
            executed.extend(wheel.tick());
        }

        assert!(executed.is_empty());
    }
}
