//! Tests for behavior tree support in LSP

#[cfg(test)]
mod tests {
    use crate::lsp::{
        document::Document,
        symbols,
    };

    const BEHAVIOR_SAMPLE: &str = r#"
behavior SimpleBehavior {
    walk_around
}

behavior FindFood {
    choose {
        check_hungry
        then {
            find_nearest_food
            move_to_food
            eat
        }
    }
}

behavior SocialBehavior {
    then {
        greet
        small_talk
        farewell
    }
}

behavior ComplexDecisionTree {
    choose {
        then {
            check_threat
            flee_to_safety
        }
        then {
            check_resources
            gather_resources
        }
        idle
    }
}
"#;

    #[test]
    fn test_behavior_parsing() {
        let doc = Document::new(BEHAVIOR_SAMPLE.to_string());

        if !doc.parse_errors.is_empty() {
            for err in &doc.parse_errors {
                eprintln!("Parse error: {}", err.message);
            }
        }

        assert!(doc.ast.is_some(), "Should parse behavior trees");
        assert!(doc.parse_errors.is_empty(), "Should have no parse errors");
    }

    #[test]
    fn test_behavior_symbols() {
        let doc = Document::new(BEHAVIOR_SAMPLE.to_string());

        // Should extract behavior declarations
        assert!(doc.name_table.resolve_name("SimpleBehavior").is_some());
        assert!(doc.name_table.resolve_name("FindFood").is_some());
        assert!(doc.name_table.resolve_name("SocialBehavior").is_some());
        assert!(doc.name_table.resolve_name("ComplexDecisionTree").is_some());
    }

    #[test]
    fn test_behavior_symbol_kinds() {
        use crate::resolve::names::DeclKind;

        let doc = Document::new(BEHAVIOR_SAMPLE.to_string());

        let find_food = doc.name_table.resolve_name("FindFood").unwrap();
        assert_eq!(find_food.kind, DeclKind::Behavior);
    }

    #[test]
    fn test_behavior_in_document_symbols() {
        let doc = Document::new(BEHAVIOR_SAMPLE.to_string());
        let ast = doc.ast.as_ref().unwrap();
        let mut positions = doc.positions.clone();

        let symbols = symbols::extract_symbols_from_ast(ast, &mut positions);

        // Should have behavior symbols
        let behaviors: Vec<_> = symbols
            .iter()
            .filter(|s| s.kind == tower_lsp::lsp_types::SymbolKind::MODULE)
            .collect();

        assert_eq!(behaviors.len(), 4, "Should have 4 behaviors");
        assert!(behaviors.iter().any(|b| b.name == "SimpleBehavior"));
        assert!(behaviors.iter().any(|b| b.name == "FindFood"));
        assert!(behaviors.iter().any(|b| b.name == "SocialBehavior"));
        assert!(behaviors.iter().any(|b| b.name == "ComplexDecisionTree"));
    }

    #[test]
    fn test_behavior_with_subtrees() {
        let sample = r#"
behavior WithSubtrees {
    then {
        include helpers::check_preconditions
        main_action
        include helpers::cleanup
    }
}
"#;
        let doc = Document::new(sample.to_string());

        assert!(doc.ast.is_some(), "Should parse subtrees");
        assert!(doc.name_table.resolve_name("WithSubtrees").is_some());
    }

    #[test]
    fn test_behavior_simple_action() {
        let sample = r#"
behavior SimpleAction {
    walk_around
}
"#;
        let doc = Document::new(sample.to_string());

        assert!(doc.ast.is_some(), "Should parse simple action");
        assert!(doc.name_table.resolve_name("SimpleAction").is_some());
    }

    #[test]
    fn test_behavior_selectors_and_sequences() {
        let sample = r#"
behavior SelectorExample {
    choose {
        option_one
        option_two
        default_option
    }
}

behavior SequenceExample {
    then {
        step_one
        step_two
        step_three
    }
}
"#;
        let doc = Document::new(sample.to_string());

        assert!(doc.ast.is_some(), "Should parse selectors and sequences");
        assert_eq!(doc.name_table.all_entries().count(), 2);
    }
}
