//! Reproducers for goal-column (sticky column) unit bugs.
//!
//! `Cursor::sticky_column` is defined as a *visual* column (wide-char
//! aware). Mouse click and drag used to store the *byte* column of the
//! clicked position, and bracket expansion stored a byte *position*,
//! sending later vertical moves to the wrong column. (The PageUp/PageDown
//! variant of the same unit bug is covered by unit tests in
//! `input/actions.rs`, since page motion normally routes through viewport
//! scrolling rather than the goal-column code path.)

use crate::common::harness::EditorTestHarness;
use crossterm::event::{KeyCode, KeyModifiers};

/// A mouse click after wide chars must set a *visual* goal column, so a
/// following ArrowDown lands at the same on-screen column.
#[test]
fn test_click_then_down_keeps_visual_column() {
    let mut harness = EditorTestHarness::new(80, 24).unwrap();
    harness
        .load_buffer_from_text("你好你好xyz\nabcdefghijkl")
        .unwrap();

    // 你好你好 spans 8 screen cells; "xyz" starts right after it. Clicking
    // on 'x' puts the cursor at byte 12, visual column 8.
    let (x0, y0) = harness
        .find_text_on_screen("xyz")
        .expect("first line visible");
    harness.mouse_click(x0, y0).unwrap();
    harness.send_key(KeyCode::Down, KeyModifiers::NONE).unwrap();
    harness.type_text("X").unwrap();

    // Visual goal column 8 → X lands between 'h' and 'i'. The old byte
    // goal (12) landed it at the end of the line.
    harness.assert_screen_contains("abcdefghXijkl");
}

/// A mouse drag must also record the goal column visually.
#[test]
fn test_drag_then_down_keeps_visual_column() {
    let mut harness = EditorTestHarness::new(80, 24).unwrap();
    harness
        .load_buffer_from_text("你好你好xyz\nabcdefghijkl")
        .unwrap();

    let (x0, y0) = harness
        .find_text_on_screen("xyz")
        .expect("first line visible");
    // Drag from the line start (8 cells left of "xyz") up to 'x'.
    harness.mouse_drag(x0 - 8, y0, x0, y0).unwrap();
    harness.send_key(KeyCode::Down, KeyModifiers::NONE).unwrap();
    harness.type_text("X").unwrap();

    harness.assert_screen_contains("abcdefghXijkl");
}

/// Bracket expansion ({| }, Enter) used to store the cursor's byte
/// *position* as the goal column, so later vertical movement jumped to a
/// far-right column instead of staying near the indentation.
#[test]
fn test_bracket_expansion_leaves_no_bogus_goal_column() {
    // Bracket expansion needs auto_indent + auto_close, which the harness
    // disables by default.
    let mut config = fresh::config::Config::default();
    config.editor.auto_indent = true;
    config.editor.auto_close = true;
    let mut harness = EditorTestHarness::with_config(80, 24, config).unwrap();
    // The long first line inflates byte positions so the old bug (goal
    // column = byte position) is far from any real column.
    harness
        .load_buffer_from_text("0123456789012345678901234567\n()\nabcdefghijklmnop")
        .unwrap();

    let (px, py) = harness.find_text_on_screen("()").expect("parens visible");
    // Click on ')' → cursor between the parens.
    harness.mouse_click(px + 1, py).unwrap();
    harness
        .send_key(KeyCode::Enter, KeyModifiers::NONE)
        .unwrap();

    // Mark the indent column so the assertion adapts to whatever
    // auto-indent produced.
    harness.type_text("Y").unwrap();
    let (yx, _) = harness.find_text_on_screen("Y").expect("marker visible");

    let (tx, _) = harness
        .find_text_on_screen("abcdefghijklmnop")
        .expect("target line visible");

    harness.send_key(KeyCode::Down, KeyModifiers::NONE).unwrap();
    harness.send_key(KeyCode::Down, KeyModifiers::NONE).unwrap();
    harness.type_text("X").unwrap();

    // The cursor after typing Y sits one past the marker's column; two
    // ArrowDowns must keep that column on the target line.
    let target = "abcdefghijklmnop";
    let col = (yx - tx) as usize + 1;
    assert!(col < target.len(), "indent unexpectedly wide");
    let expected = format!("{}X{}", &target[..col], &target[col..]);
    harness.assert_screen_contains(&expected);
}
