#![allow(
    clippy::unwrap_used,
    clippy::expect_used,
    clippy::needless_pass_by_value
)]

use logical_expressions::LogicalExpression;

mod condition;
use condition::Condition;

fn test_expand(expression: &str, expected: Vec<Vec<Condition>>) {
    let parsed_expression: LogicalExpression<Condition> =
        LogicalExpression::parse(expression).unwrap();
    let result = parsed_expression.expand();
    assert_eq!(result, expected);
}

#[test]
fn test_expand_single_condition() {
    test_expand("a", vec![vec![Condition::new("a")]]);
}

#[test]
fn test_expand_and_conditions() {
    test_expand(
        "a & b",
        vec![vec![Condition::new("a"), Condition::new("b")]],
    );
}

#[test]
fn test_expand_or_conditions() {
    test_expand(
        "a | b",
        vec![vec![Condition::new("a")], vec![Condition::new("b")]],
    );
}

#[test]
fn test_expand_and_or_combinations() {
    test_expand(
        "a & (b | c)",
        vec![
            vec![Condition::new("a"), Condition::new("b")],
            vec![Condition::new("a"), Condition::new("c")],
        ],
    );
}

#[test]
fn test_expand_nested_and_conditions() {
    test_expand(
        "a & (b & (c & d))",
        vec![vec![
            Condition::new("a"),
            Condition::new("b"),
            Condition::new("c"),
            Condition::new("d"),
        ]],
    );
}

#[test]
fn test_expand_nested_or_conditions() {
    test_expand(
        "a | (b | (c | d))",
        vec![
            vec![Condition::new("a")],
            vec![Condition::new("b")],
            vec![Condition::new("c")],
            vec![Condition::new("d")],
        ],
    );
}

#[test]
fn test_expand_nested_and_or_combinations() {
    test_expand(
        "a & (b | (c & (d | e)))",
        vec![
            vec![Condition::new("a"), Condition::new("b")],
            vec![
                Condition::new("a"),
                Condition::new("c"),
                Condition::new("d"),
            ],
            vec![
                Condition::new("a"),
                Condition::new("c"),
                Condition::new("e"),
            ],
        ],
    );
}

#[test]
fn test_expand_complex_expression() {
    test_expand(
        "(a & b) | (c & (d | (e & f)))",
        vec![
            vec![Condition::new("a"), Condition::new("b")],
            vec![Condition::new("c"), Condition::new("d")],
            vec![
                Condition::new("c"),
                Condition::new("e"),
                Condition::new("f"),
            ],
        ],
    );
}

#[test]
fn test_expand_balanced_tree() {
    test_expand(
        "((a & b) | (c & d)) & ((e & f) | (g & h))",
        vec![
            vec![
                Condition::new("a"),
                Condition::new("b"),
                Condition::new("e"),
                Condition::new("f"),
            ],
            vec![
                Condition::new("a"),
                Condition::new("b"),
                Condition::new("g"),
                Condition::new("h"),
            ],
            vec![
                Condition::new("c"),
                Condition::new("d"),
                Condition::new("e"),
                Condition::new("f"),
            ],
            vec![
                Condition::new("c"),
                Condition::new("d"),
                Condition::new("g"),
                Condition::new("h"),
            ],
        ],
    );
}

#[test]
fn test_expand_left_leaning_tree() {
    test_expand(
        "(((a & b) & c) & d) & e",
        vec![vec![
            Condition::new("a"),
            Condition::new("b"),
            Condition::new("c"),
            Condition::new("d"),
            Condition::new("e"),
        ]],
    );
}

#[test]
fn test_expand_right_leaning_tree() {
    test_expand(
        "a & (b & (c & (d & e)))",
        vec![vec![
            Condition::new("a"),
            Condition::new("b"),
            Condition::new("c"),
            Condition::new("d"),
            Condition::new("e"),
        ]],
    );
}
