"""Tests for dictionary file parsing."""

import pytest
from punmunch.dictionary import Dictionary
from punmunch.affix import FlagType
from punmunch.exceptions import DictionaryError


def test_simple_dictionary_parsing():
    """Test parsing of a simple dictionary."""
    dict_content = """3
word1
word2/A
word3/AB
"""
    
    lines = dict_content.strip().split('\n')
    dictionary = Dictionary()
    dictionary._parse_file(lines)
    
    assert dictionary.get_word_count() == 3
    assert dictionary.has_word("word1")
    assert dictionary.has_word("word2")
    assert dictionary.has_word("word3")
    assert dictionary.get_flags("word1") == []
    assert dictionary.get_flags("word2") == ["A"]
    assert dictionary.get_flags("word3") == ["A", "B"]


def test_dictionary_without_count():
    """Test dictionary that doesn't start with word count."""
    dict_content = """word1
word2/A
word3/BC
"""
    
    lines = dict_content.strip().split('\n')
    dictionary = Dictionary()
    dictionary._parse_file(lines)
    
    assert dictionary.get_word_count() == 3
    assert dictionary.has_word("word1")
    assert dictionary.get_flags("word2") == ["A"]


def test_long_flags():
    """Test dictionary with long flags."""
    dict_content = """2
word1/ABCD
word2/EFGH
"""
    
    lines = dict_content.strip().split('\n')
    dictionary = Dictionary(FlagType.LONG)
    dictionary._parse_file(lines)
    
    assert dictionary.get_flags("word1") == ["AB", "CD"]
    assert dictionary.get_flags("word2") == ["EF", "GH"]


def test_numeric_flags():
    """Test dictionary with numeric flags."""
    dict_content = """2
word1/123,456
word2/789
"""
    
    lines = dict_content.strip().split('\n')
    dictionary = Dictionary(FlagType.NUM)
    dictionary._parse_file(lines)
    
    assert dictionary.get_flags("word1") == ["123", "456"]
    assert dictionary.get_flags("word2") == ["789"]


def test_comments_and_empty_lines():
    """Test handling of comments and empty lines."""
    dict_content = """3

	This is a comment line starting with tab
word1
	Another comment
word2/A

word3/B
"""
    
    lines = dict_content.split('\n')  # Don't strip to preserve tabs
    dictionary = Dictionary()
    dictionary._parse_file(lines)
    
    assert dictionary.get_word_count() == 3
    assert dictionary.has_word("word1")
    assert dictionary.has_word("word2")
    assert dictionary.has_word("word3")


def test_flags_with_comments():
    """Test handling of flags with trailing comments."""
    dict_content = """2
word1/AB some comment here
word2/CD # another comment
"""
    
    lines = dict_content.strip().split('\n')
    dictionary = Dictionary()
    dictionary._parse_file(lines)
    
    assert dictionary.get_flags("word1") == ["A", "B"]
    assert dictionary.get_flags("word2") == ["C", "D"]


def test_dictionary_methods():
    """Test various dictionary methods."""
    dictionary = Dictionary()
    
    # Add words
    dictionary.add_word("test", ["A", "B"])
    dictionary.add_word("word", [])
    
    assert dictionary.has_word("test")
    assert dictionary.has_word("word")
    assert dictionary.get_flags("test") == ["A", "B"]
    assert dictionary.get_flags("word") == []
    
    # Check flags
    assert dictionary.has_flag("test", "A")
    assert dictionary.has_flag("test", "B")
    assert not dictionary.has_flag("test", "C")
    assert not dictionary.has_flag("word", "A")
    
    # Get words with flag
    assert "test" in dictionary.get_words_with_flag("A")
    assert "word" not in dictionary.get_words_with_flag("A")
    
    # Remove word
    assert dictionary.remove_word("test") == True
    assert dictionary.remove_word("nonexistent") == False
    assert not dictionary.has_word("test")
    
    # Get all words
    all_words = dictionary.get_all_words()
    assert "word" in all_words
    assert "test" not in all_words
    
    # Clear
    dictionary.clear()
    assert dictionary.get_word_count() == 0


def test_iter_entries():
    """Test iteration over dictionary entries."""
    dictionary = Dictionary()
    dictionary.add_word("word1", ["A"])
    dictionary.add_word("word2", ["B", "C"])
    dictionary.add_word("word3", [])
    
    entries = list(dictionary.iter_entries())
    assert len(entries) == 3
    
    # Check that we have all expected entries
    entry_dict = dict(entries)
    assert entry_dict["word1"] == ["A"]
    assert entry_dict["word2"] == ["B", "C"]
    assert entry_dict["word3"] == []


def test_empty_dictionary():
    """Test handling of empty dictionary."""
    dictionary = Dictionary()
    
    assert dictionary.get_word_count() == 0
    assert dictionary.get_all_words() == []
    assert not dictionary.has_word("anything")
    assert dictionary.get_flags("anything") == []
    assert list(dictionary.iter_entries()) == []


def test_unicode_words():
    """Test handling of Unicode words."""
    dict_content = """3
café/A
naïve/B  
résumé/C
"""
    
    lines = dict_content.strip().split('\n')
    dictionary = Dictionary()
    dictionary._parse_file(lines)
    
    assert dictionary.has_word("café")
    assert dictionary.has_word("naïve")
    assert dictionary.has_word("résumé")
    assert dictionary.get_flags("café") == ["A"]


def test_invalid_dictionary_entries():
    """Test handling of invalid dictionary entries."""
    # Empty word should raise error
    dict_content = """1
/A
"""
    
    lines = dict_content.strip().split('\n')
    dictionary = Dictionary()
    
    with pytest.raises(DictionaryError):
        dictionary._parse_file(lines)


def test_flag_parsing_edge_cases():
    """Test edge cases in flag parsing."""
    dictionary = Dictionary()
    
    # Empty flag string
    flags = dictionary._parse_flags("")
    assert flags == []
    
    # Flags with numeric type but malformed
    dictionary.flag_type = FlagType.NUM
    flags = dictionary._parse_flags("123,,456,")
    assert flags == ["123", "456"]  # Empty parts should be filtered out