//! Integration tests for the resolution engine

use crate::{
    resolve::names::{
        DeclKind,
        NameTable,
    },
    syntax::{
        lexer::Lexer,
        FileParser,
    },
};

fn parse(source: &str) -> crate::syntax::ast::File {
    let lexer = Lexer::new(source);
    let parser = FileParser::new();
    parser.parse(lexer).expect("Should parse successfully")
}

#[test]
fn test_name_resolution_example_file() {
    let source = r#"
        character Alice {
            age: 30
        }

        character Bob {
            age: 35
        }

        template PersonTemplate {
            age: 18..80
        }
    "#;

    let file = parse(source);
    let table = NameTable::from_file(&file).expect("Should build name table");

    // Verify all names are registered
    assert!(table.lookup(&["Alice".to_string()]).is_some());
    assert!(table.lookup(&["Bob".to_string()]).is_some());
    assert!(table.lookup(&["PersonTemplate".to_string()]).is_some());

    // Verify kind filtering
    assert_eq!(table.entries_of_kind(DeclKind::Character).count(), 2);
    assert_eq!(table.entries_of_kind(DeclKind::Template).count(), 1);
}

#[test]
fn test_use_statements_are_parsed() {
    let source = r#"
        use characters::Martha;
        use templates::{Person, NPC};
        use locations::*;

        character LocalChar {
            age: 25
        }
    "#;

    let file = parse(source);
    let table = NameTable::from_file(&file).expect("Should build name table");

    // Verify imports were collected
    assert_eq!(table.imports().len(), 3);

    // Verify local declaration is registered
    assert!(table.lookup(&["LocalChar".to_string()]).is_some());
}

#[test]
fn test_duplicate_name_error() {
    let source = r#"
        character Martha {
            age: 30
        }

        character Martha {
            age: 35
        }
    "#;

    let file = parse(source);
    let result = NameTable::from_file(&file);

    // Should fail with duplicate error
    assert!(result.is_err());
}

#[test]
fn test_fuzzy_matching_suggestion() {
    let source = r#"
        character Elizabeth {
            age: 30
        }
    "#;

    let file = parse(source);
    let table = NameTable::from_file(&file).expect("Should build name table");

    // Typo "Elizabet" should suggest "Elizabeth"
    let suggestion = table.find_suggestion("Elizabet");
    assert_eq!(suggestion, Some("Elizabeth".to_string()));

    // Typo "Elizabth" should also suggest "Elizabeth"
    let suggestion = table.find_suggestion("Elizabth");
    assert_eq!(suggestion, Some("Elizabeth".to_string()));
}

#[test]
fn test_all_declaration_kinds() {
    let source = r#"
        character C { age: 1 }
        template T { age: 1..2 }
        life_arc L {
            state s {}
        }
        schedule S {
            10:00 -> 11:00: activity { }
        }
        behavior B {
            action
        }
        institution I {
            name: "Test"
        }
        relationship R {
            C { }
            C { }
        }
        location Loc {
            name: "Place"
        }
        species Sp {
            lifespan: 100
        }
    "#;

    let file = parse(source);
    let table = NameTable::from_file(&file).expect("Should build name table");

    // All 9 declaration kinds should be represented (enum removed)
    assert_eq!(table.entries_of_kind(DeclKind::Character).count(), 1);
    assert_eq!(table.entries_of_kind(DeclKind::Template).count(), 1);
    assert_eq!(table.entries_of_kind(DeclKind::LifeArc).count(), 1);
    assert_eq!(table.entries_of_kind(DeclKind::Schedule).count(), 1);
    assert_eq!(table.entries_of_kind(DeclKind::Behavior).count(), 1);
    assert_eq!(table.entries_of_kind(DeclKind::Institution).count(), 1);
    assert_eq!(table.entries_of_kind(DeclKind::Relationship).count(), 1);
    assert_eq!(table.entries_of_kind(DeclKind::Location).count(), 1);
    assert_eq!(table.entries_of_kind(DeclKind::Species).count(), 1);
}
