/// Integration tests for `#[event_handlers]` macro with Pilot.
use lv_tui::prelude::*;
use lv_tui::Component;

// ── Basic event handlers ────────────────────────────────────────

#[derive(Component)]
struct FocusTracker {
    #[reactive(paint, copy)]
    focused: bool,
    quit_on_q: bool,
}

#[lv_tui::event_handlers]
impl FocusTracker {
    fn render(&self, cx: &mut RenderCx) {
        if self.get_focused() {
            cx.line("focused");
        } else {
            cx.line("blurred");
        }
    }

    fn focusable(&self) -> bool {
        true
    }

    fn on_focus(&mut self, cx: &mut EventCx) {
        self.set_focused(true, cx);
    }

    fn on_blur(&mut self, cx: &mut EventCx) {
        self.set_focused(false, cx);
    }

    fn on_key_q(&mut self, cx: &mut EventCx) {
        if self.quit_on_q {
            cx.quit();
        }
    }
}

impl FocusTracker {
    fn new() -> Self {
        Self {
            focused: false,
            quit_on_q: true,
        }
    }
}

// ── Char key handler ───────────────────────────────────────────

#[derive(Component)]
struct Counter {
    #[reactive(paint, copy)]
    count: i32,
}

#[lv_tui::event_handlers]
impl Counter {
    fn render(&self, cx: &mut RenderCx) {
        cx.line(&format!("count: {}", self.get_count()));
    }

    fn on_key_plus(&mut self, cx: &mut EventCx) {
        self.set_count(self.get_count() + 1, cx);
    }

    fn on_key_q(&mut self, cx: &mut EventCx) {
        cx.quit();
    }
}

impl Counter {
    fn new() -> Self {
        Self { count: 0 }
    }
}

// ── Named key handler (Enter) ───────────────────────────────────

#[derive(Component)]
struct EnterHandler {
    #[reactive(paint, copy)]
    enter_count: i32,
}

#[lv_tui::event_handlers]
impl EnterHandler {
    fn render(&self, cx: &mut RenderCx) {
        cx.line(&format!("enters: {}", self.get_enter_count()));
    }

    fn on_key_enter(&mut self, cx: &mut EventCx) {
        self.set_enter_count(self.get_enter_count() + 1, cx);
    }

    fn on_key_q(&mut self, cx: &mut EventCx) {
        cx.quit();
    }
}

impl EnterHandler {
    fn new() -> Self {
        Self { enter_count: 0 }
    }
}

// ── Tick handler ────────────────────────────────────────────────

#[derive(Component)]
struct TickCounter {
    #[reactive(paint, copy)]
    ticks: i32,
}

#[lv_tui::event_handlers]
impl TickCounter {
    fn render(&self, cx: &mut RenderCx) {
        cx.line(&format!("ticks: {}", self.get_ticks()));
    }

    fn on_tick(&mut self, cx: &mut EventCx) {
        self.set_ticks(self.get_ticks() + 1, cx);
    }

    fn on_key_q(&mut self, cx: &mut EventCx) {
        cx.quit();
    }
}

impl TickCounter {
    fn new() -> Self {
        Self { ticks: 0 }
    }
}

// ── Space key handler ──────────────────────────────────────────

#[derive(Component)]
struct Toggle {
    #[reactive(paint, copy)]
    toggled: bool,
}

#[lv_tui::event_handlers]
impl Toggle {
    fn render(&self, cx: &mut RenderCx) {
        if self.get_toggled() {
            cx.line("[X]");
        } else {
            cx.line("[ ]");
        }
    }

    fn on_key_space(&mut self, cx: &mut EventCx) {
        self.set_toggled(!self.get_toggled(), cx);
    }

    fn on_key_q(&mut self, cx: &mut EventCx) {
        cx.quit();
    }
}

impl Toggle {
    fn new() -> Self {
        Self { toggled: false }
    }
}

// ── Tests ──────────────────────────────────────────────────────

#[test]
fn test_initial_render_unfocused() {
    let pilot = Pilot::new(FocusTracker::new(), 20, 3);
    // Initial state before any focus: should render "blurred"
    assert!(pilot.frame().cells.iter().any(|c| c.symbol == "b"));
}

#[test]
fn test_key_handler_with_quit() {
    let mut pilot = Pilot::new(FocusTracker::new(), 20, 3);
    pilot.press(Key::Char('q')).unwrap();
    assert!(pilot.has_quit());
}

#[test]
fn test_key_handler_with_plus() {
    let mut pilot = Pilot::new(Counter::new(), 20, 3);
    pilot.focus_first();

    pilot.press(Key::Char('+')).unwrap();
    pilot.press(Key::Char('+')).unwrap();

    assert!(pilot.frame().cells.iter().any(|c| c.symbol == "2"));
}

#[test]
fn test_named_key_handler() {
    let mut pilot = Pilot::new(EnterHandler::new(), 20, 3);
    pilot.focus_first();

    pilot.press(Key::Enter).unwrap();
    assert!(pilot.frame().cells.iter().any(|c| c.symbol == "1"));

    pilot.press(Key::Enter).unwrap();
    assert!(pilot.frame().cells.iter().any(|c| c.symbol == "2"));
}

#[test]
fn test_tick_handler() {
    let mut pilot = Pilot::new(TickCounter::new(), 20, 3);

    for _ in 0..5 {
        pilot.send_event(Event::Tick).unwrap();
    }

    assert!(pilot.frame().cells.iter().any(|c| c.symbol == "5"));
}

#[test]
fn test_key_space_handler() {
    let mut pilot = Pilot::new(Toggle::new(), 20, 3);
    pilot.focus_first();

    assert!(pilot.frame().cells.iter().any(|c| c.symbol == " "));

    pilot.press(Key::Char(' ')).unwrap();
    assert!(pilot.frame().cells.iter().any(|c| c.symbol == "X"));
}
