use crate::backend::{CrosstermBackend, TerminalBackend};
use crate::buffer::Buffer;
use crate::component::Component;
use crate::dirty::Dirty;
use std::cell::RefCell;
use std::time::Instant;

use crate::event::{Command, Event, EventPhase, Key, KeyEvent};
use crate::geom::Rect;
use crate::geom::Pos;
use crate::node::{Node, NodeId};
use crate::Result;

thread_local! {
    pub static COMMAND_QUEUE: RefCell<Vec<Command>> = RefCell::new(Vec::new());
    pub static DEBUG_MODE: RefCell<bool> = RefCell::new(false);
    pub static FORCE_FULL_PAINT: RefCell<bool> = RefCell::new(false);
    pub static TIMER_QUEUE: RefCell<TimerQueue> = RefCell::new(TimerQueue { requests: Vec::new(), next_id: 0 });
    /// Worker cancel flags, keyed by WorkerId.
    pub static WORKER_REGISTRY: RefCell<WorkerRegistry> = RefCell::new(WorkerRegistry { flags: std::collections::HashMap::new(), next_id: 0 });
}

/// Tracks active workers and their cancel flags.
pub struct WorkerRegistry {
    pub flags: std::collections::HashMap<crate::event::WorkerId, std::sync::Arc<std::sync::atomic::AtomicBool>>,
    pub next_id: u64,
}

/// Accumulates timer requests from component event handlers.
pub struct TimerQueue {
    pub requests: Vec<TimerRequest>,
    pub next_id: u64,
}

// ── Timer types ──────────────────────────────────────────────────

/// An action that a component can request on a timer.
pub enum TimerAction {
    /// Register a one-shot timer.
    SetOneShot { id: u64, duration_ms: u64 },
    /// Register a periodic timer.
    SetInterval { id: u64, interval_ms: u64 },
    /// Cancel a timer by id.
    Cancel { id: u64 },
}

/// A pending timer request from a component's event handler.
pub struct TimerRequest {
    pub action: TimerAction,
    pub owner: NodeId,
}

/// A live timer managed by the Runtime.
pub struct TimerEntry {
    pub id: u64,
    /// `None` for one-shot (removed after firing).
    pub interval_ms: Option<u64>,
    pub next_fire: Instant,
    pub owner: NodeId,
}

/// The application runtime.
pub struct Runtime<B: TerminalBackend = CrosstermBackend> {
    pub(crate) root: Node,
    pub(crate) backend: B,
    pub(crate) front: Buffer,
    pub(crate) back: Buffer,
    pub(crate) root_rect: Rect,
    pub(crate) quit: bool,
    pub(crate) full_paint: bool,
    pub(crate) dirty: Dirty,
    pub(crate) focused_id: Option<NodeId>,
    pub(crate) tick_rate: std::time::Duration,
    pub(crate) task_rx: std::sync::mpsc::Receiver<String>,
    pub(crate) task_tx: std::sync::mpsc::Sender<String>,
    /// Active timers.
    pub(crate) timers: Vec<TimerEntry>,
}

const ZERO_RECT: Rect = Rect {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
};

impl<B: TerminalBackend> Runtime<B> {
    /// Creates a new runtime wrapping the given root component and backend.
    pub fn new(root: impl Component + 'static, backend: B) -> Result<Self> {
        let (tx, rx) = std::sync::mpsc::channel::<String>();
        Ok(Self {
            root: Node::root(root),
            backend,
            front: Buffer::new(crate::geom::Size { width: 1, height: 1 }),
            back: Buffer::new(crate::geom::Size { width: 1, height: 1 }),
            root_rect: ZERO_RECT,
            quit: false,
            full_paint: false,
            dirty: Dirty::NONE,
            focused_id: None,
            tick_rate: std::time::Duration::from_millis(250),
            task_rx: rx,
            task_tx: tx,
            timers: Vec::new(),
        })
    }

    /// Builder: sets the tick interval (default 250ms).
    pub fn tick_rate(mut self, rate: std::time::Duration) -> Self {
        self.tick_rate = rate;
        self
    }

    /// Processes one iteration of the event loop.
    pub fn step(&mut self) -> Result<()> {
        if self.quit {
            return Ok(());
        }

        // 处理全局命令队列
        let commands: Vec<Command> = COMMAND_QUEUE.with(|q| q.borrow_mut().drain(..).collect());
        for cmd in commands {
            match cmd {
                Command::Quit => self.quit = true,
                Command::FocusNext => self.focus_next(false),
                Command::FocusPrev => self.focus_next(true),
                Command::Custom(_) => {}
            }
        }

        // 检查任务完成
        while let Ok(result) = self.task_rx.try_recv() {
            if let Some(rest) = result.strip_prefix("__worker_done__") {
                // New format: __worker_done__<id>__<payload>
                if let Some((id_str, payload)) = rest.split_once("__") {
                    if let Ok(id) = id_str.parse::<u64>() {
                        self.dispatch_event(Event::WorkerDone(
                            crate::event::WorkerId(id), payload.to_string()))?;
                    }
                }
            } else if let Some(rest) = result.strip_prefix("__worker_cancelled__") {
                if let Ok(id) = rest.parse::<u64>() {
                    self.dispatch_event(Event::WorkerDone(
                        crate::event::WorkerId(id), String::new()))?;
                }
            } else {
                // Old format: plain string from cx.spawn()
                self.dispatch_event(Event::TaskComplete(result))?;
            }
            if self.dirty.contains(Dirty::PAINT) {
                self.paint_frame()?;
                self.dirty = Dirty::NONE;
            }
        }

        // 处理过期的定时器
        let now = Instant::now();
        let mut expired: Vec<(u64, Option<u64>, NodeId)> = Vec::new(); // (id, interval_ms, owner)
        let mut i = 0;
        while i < self.timers.len() {
            if now >= self.timers[i].next_fire {
                let entry = &self.timers[i];
                expired.push((entry.id, entry.interval_ms, entry.owner));
                self.timers.remove(i);
            } else {
                i += 1;
            }
        }

        for (id, interval_ms, owner) in expired {
            self.dispatch_to_target(owner, &Event::Timer(id));

            if self.dirty.intersects(Dirty::LAYOUT | Dirty::TREE) {
                self.layout_children()?;
            }
            if self.dirty.contains(Dirty::PAINT) {
                self.paint_frame()?;
                self.dirty = Dirty::NONE;
            }

            // Re-add periodic timer for next interval
            if let Some(interval) = interval_ms {
                self.timers.push(TimerEntry {
                    id,
                    interval_ms: Some(interval),
                    next_fire: now + std::time::Duration::from_millis(interval),
                    owner,
                });
            }
        }

        // Calculate poll timeout — use smallest of tick_rate and next timer fire
        let poll_timeout = if self.task_rx.try_recv().is_ok() {
            std::time::Duration::from_millis(0)
        } else {
            let next_timer = self.timers.iter().map(|t| {
                let remaining = t.next_fire.duration_since(now);
                if remaining.as_millis() > 0 {
                    remaining
                } else {
                    std::time::Duration::from_millis(0)
                }
            }).min();
            match next_timer {
                Some(t) if t < self.tick_rate => t,
                _ => self.tick_rate,
            }
        };

        let event = match self.backend.poll_event(poll_timeout)? {
            Some(e) => e,
            None => Event::Tick,
        };
        self.dispatch_event(event)?;

        // Process timer requests collected during event dispatch
        self.process_timer_requests();

        if self.dirty.intersects(Dirty::LAYOUT | Dirty::TREE) {
            self.layout_children()?;
        }

        if self.dirty.contains(Dirty::PAINT) {
            self.paint_frame()?;
            self.dirty = Dirty::NONE;
        }

        Ok(())
    }

    /// Drains TIMER_QUEUE and applies set/interval/cancel requests.
    pub(crate) fn process_timer_requests(&mut self) {
        let requests: Vec<TimerRequest> = TIMER_QUEUE.with(|q| q.borrow_mut().requests.drain(..).collect());
        let now = Instant::now();
        for req in requests {
            match req.action {
                TimerAction::SetOneShot { id, duration_ms } => {
                    self.timers.push(TimerEntry {
                        id,
                        interval_ms: None,
                        next_fire: now + std::time::Duration::from_millis(duration_ms),
                        owner: req.owner,
                    });
                }
                TimerAction::SetInterval { id, interval_ms } => {
                    self.timers.push(TimerEntry {
                        id,
                        interval_ms: Some(interval_ms),
                        next_fire: now + std::time::Duration::from_millis(interval_ms),
                        owner: req.owner,
                    });
                }
                TimerAction::Cancel { id } => {
                    self.timers.retain(|t| t.id != id);
                }
            }
        }
    }

    /// Starts the event loop. Blocks until the application exits.
    pub fn run(&mut self) -> Result<()> {
        self.backend.enter()?;
        self.initial_layout_and_paint()?;
        // Process timer requests from mount() lifecycle
        self.process_timer_requests();

        while !self.quit {
            self.step()?;
        }

        // 卸载生命周期
        self.root.unmount(&mut self.dirty, &mut self.quit, Some(self.task_tx.clone()));
        self.backend.leave()?;
        Ok(())
    }

    pub fn initial_layout_and_paint(&mut self) -> Result<()> {
        let size = self.backend.size()?;

        self.root_rect = Rect {
            x: 0,
            y: 0,
            width: size.width,
            height: size.height,
        };

        self.front = Buffer::new(size);
        self.back = Buffer::new(size);

        self.full_paint = true;
        self.dirty = Dirty::LAYOUT | Dirty::PAINT;

        self.layout_children()?;

        // 挂载生命周期
        self.root.mount(&mut self.dirty, &mut self.quit, Some(self.task_tx.clone()));

        // 启动时自动聚焦第一个可聚焦组件
        let mut ids = Vec::new();
        self.root.collect_focusable(&mut ids);
        if !ids.is_empty() {
            self.focused_id = Some(ids[0]);
        }

        self.paint_frame()?;
        self.dirty = Dirty::NONE;

        Ok(())
    }

    fn dispatch_event(&mut self, event: Event) -> Result<()> {
        match event {
            Event::Resize(size) => {
                let new_rect = Rect {
                    x: 0,
                    y: 0,
                    width: size.width,
                    height: size.height,
                };

                if new_rect != self.root_rect {
                    self.root_rect = new_rect;
                    self.front.resize(size);
                    self.back.resize(size);
                    self.full_paint = true;
                    self.dirty = Dirty::LAYOUT | Dirty::PAINT;
                }
            }
            Event::Key(KeyEvent { key: Key::Tab, modifiers }) => {
                self.focus_next(modifiers.shift);
            }
            Event::Mouse(mouse_event) => {
                let pos = Pos {
                    x: mouse_event.x,
                    y: mouse_event.y,
                };
                if let Some(id) = self.root.hit_test(pos) {
                    self.dispatch_to_target(id, &Event::Mouse(mouse_event));
                }
            }
            Event::Focus | Event::Blur => {
                // 焦点事件由 set_focus 内发送
            }
            other => {
                // 键盘等事件发给焦点组件（有焦点时）或 root
                let target = self.focused_id.unwrap_or(NodeId::ROOT);
                self.dispatch_to_target(target, &other);
            }
        }

        Ok(())
    }

    pub(crate) fn focus_next(&mut self, backwards: bool) {
        let mut ids = Vec::new();
        self.root.collect_focusable(&mut ids);

        if ids.is_empty() {
            return;
        }

        let old_id = self.focused_id;

        let new_idx = match old_id {
            None => {
                if backwards {
                    ids.len() - 1
                } else {
                    0
                }
            }
            Some(old) => {
                if let Some(pos) = ids.iter().position(|id| *id == old) {
                    if backwards {
                        if pos == 0 {
                            ids.len() - 1
                        } else {
                            pos - 1
                        }
                    } else if pos + 1 >= ids.len() {
                        0
                    } else {
                        pos + 1
                    }
                } else {
                    0
                }
            }
        };

        let new_id = ids[new_idx];
        self.set_focus(new_id);
    }

    /// 三阶段事件分发：capture → target → bubble
    fn dispatch_to_target(&mut self, target_id: NodeId, event: &Event) {
        // 找到从 root 到 target 的完整路径
        let (path, effective_target) = match self.root.find_path_to(target_id) {
                Some(p) => (p, target_id),
                None => (vec![NodeId::ROOT], NodeId::ROOT),
            };

        let mut stopped = false;

        // Capture: root → target 的祖先（正序，不含 target 自身）
        for &node_id in &path[..path.len().saturating_sub(1)] {
            if stopped {
                break;
            }
            self.root.send_event(
                node_id,
                event,
                &mut self.dirty,
                &mut self.quit,
                EventPhase::Capture,
                &mut stopped,
                Some(self.task_tx.clone()),
            );
        }

        // Target: 目标自身
        if !stopped {
            self.root.send_event(
                effective_target,
                event,
                &mut self.dirty,
                &mut self.quit,
                EventPhase::Target,
                &mut stopped,
                Some(self.task_tx.clone()),
            );
        }

        // Bubble: target 的祖先 → root（逆序，不含 target）
        for &node_id in path[..path.len().saturating_sub(1)].iter().rev() {
            if stopped {
                break;
            }
            self.root.send_event(
                node_id,
                event,
                &mut self.dirty,
                &mut self.quit,
                EventPhase::Bubble,
                &mut stopped,
                Some(self.task_tx.clone()),
            );
        }
    }

    fn set_focus(&mut self, new_id: NodeId) {
        let old_id = self.focused_id;

        // 发送 Blur 给旧焦点（直接目标，不冒泡）
        if let Some(old) = old_id {
            if old != new_id {
                let mut stopped = false;
                self.root.send_event(
                    old,
                    &Event::Blur,
                    &mut self.dirty,
                    &mut self.quit,
                    EventPhase::Target,
                    &mut stopped,
                Some(self.task_tx.clone()),
                );
            }
        }

        self.focused_id = Some(new_id);

        // 发送 Focus 给新焦点
        if old_id != Some(new_id) {
            let mut stopped = false;
            self.root.send_event(
                new_id,
                &Event::Focus,
                &mut self.dirty,
                &mut self.quit,
                EventPhase::Target,
                &mut stopped,
                Some(self.task_tx.clone()),
            );
        }

        self.dirty |= Dirty::PAINT;
    }

    pub(crate) fn layout_children(&mut self) -> Result<()> {
        self.root.layout(self.root_rect);
        Ok(())
    }

    pub(crate) fn paint_frame(&mut self) -> Result<()> {
        self.back.clear();
        self.root.render_with_clip(&mut self.back, self.focused_id, None);

        // 全局 debug 渲染
        if DEBUG_MODE.with(|d| *d.borrow()) {
            self.root.debug_render(&mut self.back, self.focused_id);
        }

        if self.full_paint || FORCE_FULL_PAINT.with(|f| f.replace(false)) {
            let ops = self.back.all_ops();
            self.backend.flush(&ops)?;
            self.full_paint = false;
        } else {
            let ops = self.front.diff(&self.back);
            self.backend.flush(&ops)?;
        }

        std::mem::swap(&mut self.front, &mut self.back);

        Ok(())
    }
}
