"""Tests for the main Punmunch class."""

import pytest
from pathlib import Path
from punmunch.unmunch import Punmunch
from punmunch.exceptions import PunmunchError


def create_test_affix_file(path: Path):
    """Create a test affix file."""
    content = """SET UTF-8
TRY esn

PFX U Y 1
PFX U 0 un .

SFX S Y 2
SFX S 0 s [^s]
SFX S 0 es s

SFX Y Y 1  
SFX Y y ies y
"""
    path.write_text(content)


def create_test_dictionary_file(path: Path):
    """Create a test dictionary file."""
    content = """4
cat/S
dog/S
happy/SUY
try/Y
"""
    path.write_text(content)


def test_punmunch_basic_usage(tmp_path):
    """Test basic Punmunch usage."""
    aff_file = tmp_path / "test.aff"
    dic_file = tmp_path / "test.dic"
    
    create_test_affix_file(aff_file)
    create_test_dictionary_file(dic_file)
    
    punmunch = Punmunch()
    punmunch.load_affix_file(aff_file)
    punmunch.load_dictionary(dic_file)
    
    # Test single word expansion
    expanded = punmunch.expand_word("cat")
    assert "cat" in expanded
    assert "cats" in expanded
    
    # Test multiple word expansion
    expanded = punmunch.expand_words(["cat", "dog"])
    assert "cat" in expanded
    assert "cats" in expanded
    assert "dog" in expanded
    assert "dogs" in expanded


def test_punmunch_unmunch_all(tmp_path):
    """Test unmunching entire dictionary."""
    aff_file = tmp_path / "test.aff"
    dic_file = tmp_path / "test.dic"
    
    create_test_affix_file(aff_file)
    create_test_dictionary_file(dic_file)
    
    punmunch = Punmunch()
    punmunch.load_affix_file(aff_file)
    punmunch.load_dictionary(dic_file)
    
    all_forms = punmunch.unmunch_all()
    
    # Should contain original words
    assert "cat" in all_forms
    assert "dog" in all_forms
    assert "happy" in all_forms
    assert "try" in all_forms
    
    # Should contain expanded forms
    assert "cats" in all_forms
    assert "dogs" in all_forms  
    assert "happys" in all_forms
    assert "tries" in all_forms
    assert "unhappy" in all_forms


def test_punmunch_expand_mode(tmp_path):
    """Test expand mode (without dictionary validation)."""
    aff_file = tmp_path / "test.aff"
    dic_file = tmp_path / "test.dic"
    
    create_test_affix_file(aff_file)
    create_test_dictionary_file(dic_file)
    
    punmunch = Punmunch()
    punmunch.load_affix_file(aff_file)
    punmunch.load_dictionary(dic_file)
    
    # Test with dictionary validation
    expanded = punmunch.expand_words(["cat"], use_dictionary=True)
    assert "cat" in expanded
    assert "cats" in expanded
    
    # Test without dictionary validation (should try all rules)
    expanded = punmunch.expand_words(["randomword"], use_dictionary=False)
    assert "randomword" in expanded
    # May contain various forms depending on which rules apply


def test_punmunch_word_validation(tmp_path):
    """Test word validation functionality."""
    aff_file = tmp_path / "test.aff" 
    dic_file = tmp_path / "test.dic"
    
    create_test_affix_file(aff_file)
    create_test_dictionary_file(dic_file)
    
    punmunch = Punmunch()
    punmunch.load_affix_file(aff_file)
    punmunch.load_dictionary(dic_file)
    
    # Dictionary words should be valid
    assert punmunch.is_valid_word("cat")
    assert punmunch.is_valid_word("dog")
    
    # Expanded forms should be valid
    assert punmunch.is_valid_word("cats")
    assert punmunch.is_valid_word("tries")
    
    # Random words should not be valid
    assert not punmunch.is_valid_word("randomword")


def test_punmunch_get_root_words(tmp_path):
    """Test finding root words for surface forms."""
    aff_file = tmp_path / "test.aff"
    dic_file = tmp_path / "test.dic"
    
    create_test_affix_file(aff_file)
    create_test_dictionary_file(dic_file)
    
    punmunch = Punmunch()
    punmunch.load_affix_file(aff_file)
    punmunch.load_dictionary(dic_file)
    
    # Find root for expanded form
    roots = punmunch.get_root_words("cats")
    assert "cat" in roots
    
    roots = punmunch.get_root_words("tries")
    assert "try" in roots
    
    roots = punmunch.get_root_words("unhappy")
    assert "happy" in roots
    
    # Root word should return itself
    roots = punmunch.get_root_words("cat")
    assert "cat" in roots


def test_punmunch_statistics(tmp_path):
    """Test statistics functionality."""
    aff_file = tmp_path / "test.aff"
    dic_file = tmp_path / "test.dic"
    
    create_test_affix_file(aff_file)
    create_test_dictionary_file(dic_file)
    
    punmunch = Punmunch()
    
    # Stats before loading
    stats = punmunch.get_statistics()
    assert not stats['affix_file_loaded']
    assert not stats['dictionary_loaded']
    assert stats['word_count'] == 0
    
    # Stats after loading affix file
    punmunch.load_affix_file(aff_file)
    stats = punmunch.get_statistics()
    assert stats['affix_file_loaded']
    assert not stats['dictionary_loaded']
    assert stats['flag_type'] == 'char'
    assert stats['encoding'] == 'UTF-8'
    assert stats['prefix_flags'] == 1
    assert stats['suffix_flags'] == 2
    
    # Stats after loading dictionary
    punmunch.load_dictionary(dic_file)
    stats = punmunch.get_statistics()
    assert stats['dictionary_loaded']
    assert stats['word_count'] == 4


def test_punmunch_error_handling(tmp_path):
    """Test error handling."""
    punmunch = Punmunch()
    
    # Should fail without affix file
    with pytest.raises(PunmunchError):
        punmunch.unmunch_all()
    
    with pytest.raises(PunmunchError):
        punmunch.expand_words(["test"])
    
    # Should fail loading dictionary without affix file
    dic_file = tmp_path / "test.dic"
    create_test_dictionary_file(dic_file)
    
    with pytest.raises(PunmunchError):
        punmunch.load_dictionary(dic_file)
    
    # Should handle missing files
    with pytest.raises(Exception):  # File not found error
        punmunch.load_affix_file("nonexistent.aff")


def test_punmunch_empty_results():
    """Test handling of empty results."""
    punmunch = Punmunch()
    
    # Without loading anything, validation should return False
    assert not punmunch.is_valid_word("test")
    assert punmunch.get_root_words("test") == []


def test_punmunch_file_path_handling(tmp_path):
    """Test handling of different file path types."""
    aff_file = tmp_path / "test.aff"
    dic_file = tmp_path / "test.dic"
    
    create_test_affix_file(aff_file)
    create_test_dictionary_file(dic_file)
    
    punmunch = Punmunch()
    
    # Test with Path objects
    punmunch.load_affix_file(aff_file)
    punmunch.load_dictionary(dic_file)
    
    # Should work
    stats = punmunch.get_statistics()
    assert stats['affix_file_loaded']
    assert stats['dictionary_loaded']
    
    # Test with string paths
    punmunch2 = Punmunch()
    punmunch2.load_affix_file(str(aff_file))
    punmunch2.load_dictionary(str(dic_file))
    
    # Should also work
    stats2 = punmunch2.get_statistics()
    assert stats2['affix_file_loaded'] 
    assert stats2['dictionary_loaded']