use crate::dirty::Dirty;
use crate::event::{Command, Event, EventPhase};
use crate::geom::{Rect, Size};
use crate::layout::Constraint;
use crate::node::Node;
use crate::render::RenderCx;
use crate::style::Style;

/// 组件 trait——应用的基本组织单元
pub trait Component {
    /// 渲染组件内容
    fn render(&self, cx: &mut RenderCx);

    /// 处理事件（可选实现）
    fn event(&mut self, _event: &Event, _cx: &mut EventCx) {}

    /// 返回组件样式（可选实现）
    fn style(&self) -> Style {
        Style::default()
    }

    /// 测量组件在给定约束下的自适应尺寸
    ///
    /// 默认实现：单行高度，宽度填满可用空间。
    fn measure(&self, constraint: Constraint, _cx: &mut MeasureCx) -> Size {
        Size {
            width: constraint.max.width,
            height: 1,
        }
    }

    /// 布局回调——组件在此计算子节点 rect 并调用 child.layout()
    ///
    /// 默认实现：无子节点，不执行任何操作。
    fn layout(&mut self, _rect: Rect, _cx: &mut LayoutCx) {}

    /// 首次挂载（初始化后调用）
    fn mount(&mut self, _cx: &mut EventCx) {}
    /// 从树卸载（退出前调用）
    fn unmount(&mut self, _cx: &mut EventCx) {}
    /// 每次事件分发前调用
    fn update(&mut self, _cx: &mut EventCx) {}

    /// 组件类型名（用于样式表类型选择器匹配）
    fn type_name(&self) -> &str {
        std::any::type_name::<Self>()
            .split("::")
            .last()
            .unwrap_or("Unknown")
    }

    /// 组件 ID（用于样式表 #id 选择器匹配）
    fn id(&self) -> Option<&str> {
        None
    }

    /// 组件 class（用于样式表 .class 选择器匹配）
    fn class(&self) -> Option<&str> {
        None
    }

    /// 是否可聚焦（Tab 导航会跳过不可聚焦的组件）
    fn focusable(&self) -> bool {
        true
    }

    /// 遍历子节点（为焦点系统等提供统一的树遍历接口）
    fn for_each_child(&self, _f: &mut dyn FnMut(&Node)) {}

    /// 遍历子节点（可变版本）
    fn for_each_child_mut(&mut self, _f: &mut dyn FnMut(&mut Node)) {}
}

/// 事件上下文——组件通过它标记 dirty、退出应用等
///
/// 每个 Node 拥有独立的 EventCx，dirty 标记精确到当前节点，
/// 同时通过 global_dirty 确保 Runtime 感知到变更。
pub struct EventCx<'a> {
    pub(crate) node_dirty: &'a mut Dirty,
    pub(crate) global_dirty: &'a mut Dirty,
    pub(crate) quit: &'a mut bool,
    pub(crate) phase: EventPhase,
    pub(crate) propagation_stopped: &'a mut bool,
    pub(crate) task_sender: Option<std::sync::mpsc::Sender<String>>,
    /// The NodeId of the component currently handling this event.
    pub(crate) current_node_id: crate::node::NodeId,
}

impl<'a> EventCx<'a> {
    pub(crate) fn new(
        node_dirty: &'a mut Dirty,
        global_dirty: &'a mut Dirty,
        quit: &'a mut bool,
        phase: EventPhase,
        propagation_stopped: &'a mut bool,
    ) -> Self {
        Self {
            node_dirty,
            global_dirty,
            quit,
            phase,
            propagation_stopped,
            task_sender: None,
            current_node_id: crate::node::NodeId::ROOT,
        }
    }

    pub(crate) fn with_task_sender(
        node_dirty: &'a mut Dirty,
        global_dirty: &'a mut Dirty,
        quit: &'a mut bool,
        phase: EventPhase,
        propagation_stopped: &'a mut bool,
        task_sender: Option<std::sync::mpsc::Sender<String>>,
    ) -> Self {
        Self {
            node_dirty,
            global_dirty,
            quit,
            phase,
            propagation_stopped,
            task_sender,
            current_node_id: crate::node::NodeId::ROOT,
        }
    }

    /// 当前事件传播阶段
    pub fn phase(&self) -> EventPhase {
        self.phase
    }

    /// 停止事件传播（后续阶段和祖先不再收到该事件）
    pub fn stop_propagation(&mut self) {
        *self.propagation_stopped = true;
    }

    /// 标记当前节点需要重绘
    pub fn invalidate_paint(&mut self) {
        *self.node_dirty |= Dirty::PAINT;
        *self.global_dirty |= Dirty::PAINT;
    }

    /// 标记当前节点需要重新布局并重绘
    pub fn invalidate_layout(&mut self) {
        *self.node_dirty |= Dirty::LAYOUT | Dirty::PAINT;
        *self.global_dirty |= Dirty::LAYOUT | Dirty::PAINT;
    }

    /// 标记需要重新布局（等同于 invalidate_layout）
    pub fn invalidate(&mut self) {
        self.invalidate_layout();
    }

    /// 标记组件树结构变化，触发完整 rebuild + relayout + repaint
    pub fn invalidate_tree(&mut self) {
        *self.node_dirty |= Dirty::TREE | Dirty::LAYOUT | Dirty::PAINT;
        *self.global_dirty |= Dirty::TREE | Dirty::LAYOUT | Dirty::PAINT;
    }

    /// Copy text to the system clipboard via OSC 52.
    ///
    /// Most modern terminals support this. The escape sequence is written
    /// directly to stdout.
    pub fn copy_to_clipboard(&self, text: &str) {
        use std::io::Write;
        let seq = crate::clipboard::copy_to_clipboard_sequence(text);
        let _ = std::io::stdout().write_all(seq.as_bytes());
        let _ = std::io::stdout().flush();
    }

    /// 退出应用
    pub fn quit(&mut self) {
        *self.quit = true;
    }

    /// 发送命令给 Runtime 统一处理（通过全局队列）
    pub fn dispatch(&mut self, cmd: Command) {
        crate::runtime::COMMAND_QUEUE.with(|q| {
            q.borrow_mut().push(cmd);
        });
    }

    /// 切换 debug 视图
    pub fn toggle_debug() {
        crate::runtime::DEBUG_MODE.with(|d| {
            let current = *d.borrow();
            *d.borrow_mut() = !current;
        });
    }

    /// 启动后台任务
    pub fn spawn<F>(&mut self, task: F)
    where
        F: FnOnce() -> String + Send + 'static,
    {
        if let Some(tx) = self.task_sender.clone() {
            std::thread::spawn(move || {
                let result = task();
                let _ = tx.send(result);
            });
        }
    }

    /// 启动可追踪的后台任务。返回 WorkerId 用于取消。
    pub fn spawn_worker<F>(&mut self, task: F) -> crate::event::WorkerId
    where
        F: FnOnce() -> String + Send + 'static,
    {
        use crate::event::WorkerId;
        use crate::runtime::WORKER_REGISTRY;
        use std::sync::{Arc, atomic::{AtomicBool, Ordering}};

        let id = WORKER_REGISTRY.with(|r| {
            let mut r = r.borrow_mut();
            let id = WorkerId(r.next_id);
            r.next_id += 1;
            id
        });

        let cancel_flag = Arc::new(AtomicBool::new(false));
        WORKER_REGISTRY.with(|r| {
            r.borrow_mut().flags.insert(id, cancel_flag.clone());
        });

        if let Some(tx) = self.task_sender.clone() {
            let flag = cancel_flag.clone();
            std::thread::spawn(move || {
                if flag.load(Ordering::Relaxed) {
                    let _ = tx.send(format!("__worker_cancelled__{}", id.0));
                    return;
                }
                let result = task();
                if flag.load(Ordering::Relaxed) {
                    let _ = tx.send(format!("__worker_cancelled__{}", id.0));
                    return;
                }
                let _ = tx.send(format!("__worker_done__{}__{}", id.0, result));
            });
        }

        id
    }

    /// 取消指定 Worker。
    pub fn cancel_worker(&mut self, id: crate::event::WorkerId) {
        use std::sync::atomic::Ordering;
        crate::runtime::WORKER_REGISTRY.with(|r| {
            let r = r.borrow();
            if let Some(flag) = r.flags.get(&id) {
                flag.store(true, Ordering::Relaxed);
            }
        });
    }

    /// Registers a one-shot timer. After `duration_ms` milliseconds,
    /// an `Event::Timer(id)` is dispatched to this component and the timer
    /// is automatically removed. Returns the timer id.
    pub fn set_timer(&mut self, duration_ms: u64) -> u64 {
        crate::runtime::TIMER_QUEUE.with(|q| {
            let mut q = q.borrow_mut();
            let id = q.next_id;
            q.next_id += 1;
            q.requests.push(crate::runtime::TimerRequest {
                action: crate::runtime::TimerAction::SetOneShot { id, duration_ms },
                owner: self.current_node_id,
            });
            id
        })
    }

    /// Registers a periodic timer. Every `interval_ms` milliseconds,
    /// an `Event::Timer(id)` is dispatched to this component. The timer
    /// continues until `cancel_timer(id)` is called or the component is
    /// unmounted. Returns the timer id.
    pub fn set_interval(&mut self, interval_ms: u64) -> u64 {
        crate::runtime::TIMER_QUEUE.with(|q| {
            let mut q = q.borrow_mut();
            let id = q.next_id;
            q.next_id += 1;
            q.requests.push(crate::runtime::TimerRequest {
                action: crate::runtime::TimerAction::SetInterval { id, interval_ms },
                owner: self.current_node_id,
            });
            id
        })
    }

    /// Cancels a previously registered timer. No further `Event::Timer`
    /// events will be dispatched for this id.
    pub fn cancel_timer(&mut self, timer_id: u64) {
        crate::runtime::TIMER_QUEUE.with(|q| {
            q.borrow_mut().requests.push(crate::runtime::TimerRequest {
                action: crate::runtime::TimerAction::Cancel { id: timer_id },
                owner: self.current_node_id,
            });
        })
    }
}

/// 测量上下文——组件通过它测量自身和子组件的自适应尺寸
pub struct MeasureCx {
    pub constraint: Constraint,
}

/// 布局上下文——容器组件通过它为子节点分配 Rect
pub struct LayoutCx<'a> {
    children: &'a mut Vec<Node>,
}

impl<'a> LayoutCx<'a> {
    pub(crate) fn new(children: &'a mut Vec<Node>) -> Self {
        Self { children }
    }

    /// 获取子节点数量
    pub fn child_count(&self) -> usize {
        self.children.len()
    }

    /// 获取第 i 个子节点的 style
    pub fn child_style(&self, index: usize) -> Option<Style> {
        self.children.get(index).map(|n| n.component.style())
    }

    /// 为第 i 个子节点设置布局 rect（递归触发子节点 layout）
    pub fn layout_child(&mut self, index: usize, rect: Rect) {
        if let Some(child) = self.children.get_mut(index) {
            child.layout(rect);
        }
    }

    /// 遍历所有子节点
    pub fn for_each_child(&mut self, mut f: impl FnMut(usize, &mut Node)) {
        for (i, child) in self.children.iter_mut().enumerate() {
            f(i, child);
        }
    }
}
