use super::harness::*;
use cagire::forth::Value;

fn int(n: i64) -> Value {
    Value::Int(n, None)
}

#[test]
fn range_ascending() {
    expect_stack("1 4 ..", &[int(1), int(2), int(3), int(4)]);
}

#[test]
fn range_descending() {
    expect_stack("4 1 ..", &[int(4), int(3), int(2), int(1)]);
}

#[test]
fn range_single() {
    expect_stack("3 3 ..", &[int(3)]);
}

#[test]
fn range_negative() {
    expect_stack("-2 1 ..", &[int(-2), int(-1), int(0), int(1)]);
}

#[test]
fn range_underflow() {
    expect_error("1 ..", "stack underflow");
    expect_error("..", "stack underflow");
}

#[test]
fn gen_basic() {
    expect_stack("( 42 ) 3 gen", &[int(42), int(42), int(42)]);
}

#[test]
fn gen_with_computation() {
    // Each iteration: dup current value, add 1, result is new value
    // 0 → dup(0,0) 1+(0,1) → pop 1, stack [0]
    // 0 → dup(0,0) 1+(0,1) → pop 1, stack [0]
    // So we get [0, 1, 1, 1] - the 0 stays, we collect three 1s
    expect_stack("0 ( dup 1 + ) 3 gen", &[int(0), int(1), int(1), int(1)]);
}

#[test]
fn gen_chained() {
    // Start with 1, each iteration: dup, multiply by 2
    // 1 → dup(1,1) 2*(1,2) → pop 2, stack [1]
    // 1 → dup(1,1) 2*(1,2) → pop 2, stack [1]
    expect_stack("1 ( dup 2 * ) 3 gen", &[int(1), int(2), int(2), int(2)]);
}

#[test]
fn gen_zero() {
    expect_stack("( 1 ) 0 gen", &[]);
}

#[test]
fn gen_underflow() {
    expect_error("3 gen", "stack underflow");
}

#[test]
fn gen_not_a_number() {
    expect_error("( 1 ) gen", "expected number");
}

#[test]
fn gen_negative() {
    expect_error("( 1 ) -1 gen", "gen count must be >= 0");
}

#[test]
fn gen_empty_quot_error() {
    expect_error("( ) 3 gen", "quotation must produce");
}

#[test]
fn geom_growing() {
    expect_stack("1 2 4 geom..", &[int(1), int(2), int(4), int(8)]);
}

#[test]
fn geom_shrinking() {
    expect_stack("8 0.5 4 geom..", &[int(8), int(4), int(2), int(1)]);
}

#[test]
fn geom_single() {
    expect_stack("5 2 1 geom..", &[int(5)]);
}

#[test]
fn geom_zero_count() {
    expect_stack("1 2 0 geom..", &[]);
}

#[test]
fn geom_underflow() {
    expect_error("1 2 geom..", "stack underflow");
}

#[test]
fn step_range_ascending() {
    expect_stack("0 1 0.25 .,", &[
        int(0),
        Value::Float(0.25, None),
        Value::Float(0.5, None),
        Value::Float(0.75, None),
        int(1),
    ]);
}

#[test]
fn step_range_descending() {
    expect_stack("1 0 -0.5 .,", &[
        int(1),
        Value::Float(0.5, None),
        int(0),
    ]);
}

#[test]
fn step_range_integer_step() {
    expect_stack("0 6 2 .,", &[int(0), int(2), int(4), int(6)]);
}

#[test]
fn step_range_single() {
    expect_stack("5 5 1 .,", &[int(5)]);
}

#[test]
fn step_range_zero_step_error() {
    expect_error("0 10 0 .,", "step cannot be zero");
}

#[test]
fn step_range_underflow() {
    expect_error("0 1 .,", "stack underflow");
}
