//! Tests for semantic validation integration

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

    #[test]
    fn test_reserved_keyword_caught_by_parser() {
        // Reserved keywords are caught by the parser, not the validator
        // This test verifies that parse errors catch reserved keywords
        let source = r#"
character Alice {
    self: "Bad field name"
}
"#;
        let doc = Document::new(source.to_string());

        // Should have parse error for reserved keyword
        assert!(
            !doc.parse_errors.is_empty(),
            "Parser should catch reserved keyword 'self' as field name"
        );
    }

    #[test]
    fn test_valid_fields_no_validation_errors() {
        let source = r#"
character Alice {
    age: 7
    name: "Alice"
}
"#;
        let doc = Document::new(source.to_string());

        // Should have no validation errors
        assert!(
            doc.resolve_errors.is_empty(),
            "Valid code should have no validation errors"
        );
    }

    #[test]
    fn test_trait_range_validation() {
        let source = r#"
character Alice {
    bond: 1.5
}
"#;
        let doc = Document::new(source.to_string());

        // Should have error for bond value out of range
        assert!(
            !doc.resolve_errors.is_empty(),
            "Should detect bond value out of range [0.0, 1.0]"
        );

        let error_message = format!("{}", doc.resolve_errors[0]);
        assert!(
            error_message.contains("1.5") || error_message.contains("range"),
            "Error should mention the value or range: {}",
            error_message
        );
    }

    #[test]
    fn test_valid_trait_ranges() {
        let source = r#"
character Alice {
    bond: 0.75
    trust: 0.0
    love: 1.0
}
"#;
        let doc = Document::new(source.to_string());

        // Should have no validation errors for valid trait ranges
        assert!(
            doc.resolve_errors.is_empty(),
            "Valid trait values should produce no errors"
        );
    }

    #[test]
    fn test_life_arc_transition_validation() {
        let source = r#"
life_arc Growing {
    state child {
        on birthday -> adult
    }
}
"#;
        let doc = Document::new(source.to_string());

        // Should have error for transition to unknown state 'adult'
        assert!(
            !doc.resolve_errors.is_empty(),
            "Should detect transition to undefined state"
        );

        let error_message = format!("{}", doc.resolve_errors[0]);
        assert!(
            error_message.contains("adult") || error_message.contains("unknown"),
            "Error should mention unknown state"
        );
    }

    #[test]
    fn test_valid_life_arc_transitions() {
        let source = r#"
life_arc Growing {
    state child {
        on birthday -> teen
    }
    state teen {
        on birthday -> adult
    }
    state adult {}
}
"#;
        let doc = Document::new(source.to_string());

        // Should have no validation errors
        assert!(
            doc.resolve_errors.is_empty(),
            "Valid life arc should produce no errors"
        );
    }

    #[test]
    fn test_schedule_overlap_validation() {
        let source = r#"
schedule Daily {
    08:00 -> 10:00: morning {}
    09:00 -> 11:00: overlap {}
}
"#;
        let doc = Document::new(source.to_string());

        // Should have error for overlapping schedule blocks
        assert!(
            !doc.resolve_errors.is_empty(),
            "Should detect overlapping schedule blocks"
        );

        let error_message = format!("{}", doc.resolve_errors[0]);
        assert!(
            error_message.contains("overlap"),
            "Error should mention overlap"
        );
    }

    #[test]
    fn test_valid_schedule_no_overlaps() {
        let source = r#"
schedule Daily {
    08:00 -> 10:00: morning {}
    10:00 -> 12:00: midday {}
    12:00 -> 14:00: afternoon {}
}
"#;
        let doc = Document::new(source.to_string());

        // Should have no validation errors
        assert!(
            doc.resolve_errors.is_empty(),
            "Non-overlapping schedule should produce no errors"
        );
    }

    #[test]
    fn test_multiple_validation_errors() {
        // Test multiple validation errors at once
        let source = r#"
character Alice {
    bond: 2.0
    trust: -0.5
}
"#;
        let doc = Document::new(source.to_string());

        // Should have multiple errors for out-of-range values
        assert!(
            doc.resolve_errors.len() >= 2,
            "Should detect multiple range errors. Got {} errors",
            doc.resolve_errors.len()
        );
    }

    #[test]
    fn test_parse_and_validation_errors_separate() {
        let source = r#"
character Alice {
    character: "Reserved"
    invalid syntax here
}
"#;
        let doc = Document::new(source.to_string());

        // Parse should fail, so we won't have validation errors
        // (validation only runs on successfully parsed AST)
        assert!(
            !doc.parse_errors.is_empty() || !doc.resolve_errors.is_empty(),
            "Should have either parse or validation errors"
        );
    }
}
