"""Tests for POV template engine."""

from dataclasses import dataclass

import pytest

from mudlib.render.pov import render_pov


@dataclass
class MockEntity:
    """Simple entity for testing."""

    name: str


@pytest.fixture
def jared():
    """Attacker entity."""
    return MockEntity(name="Jared")


@pytest.fixture
def goku():
    """Defender entity."""
    return MockEntity(name="Goku")


@pytest.fixture
def vegeta():
    """Bystander entity."""
    return MockEntity(name="Vegeta")


def test_attacker_pov_basic(jared, goku):
    """Attacker sees 'You' for self, defender name for target."""
    template = "{attacker} hit{s} {defender}"
    result = render_pov(template, viewer=jared, attacker=jared, defender=goku)
    assert result == "You hit Goku"


def test_defender_pov_basic(jared, goku):
    """Defender sees attacker name, 'You' for self."""
    template = "{attacker} hit{s} {defender}"
    result = render_pov(template, viewer=goku, attacker=jared, defender=goku)
    assert result == "Jared hits You"


def test_bystander_pov_basic(jared, goku, vegeta):
    """Bystander sees both entity names."""
    template = "{attacker} hits {defender}"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Jared hits Goku"


def test_verb_s_conjugation_you(jared, goku):
    """Verb with {s} after You gets no suffix."""
    template = "{attacker} punch{s} {defender}"
    result = render_pov(template, viewer=jared, attacker=jared, defender=goku)
    assert result == "You punch Goku"


def test_verb_s_conjugation_third_person(jared, goku, vegeta):
    """Verb with {s} after name gets 's' suffix."""
    template = "{attacker} punch{s} {defender}"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Jared punches Goku"


def test_verb_es_conjugation_you(jared, goku):
    """Verb with {es} after You gets no suffix."""
    template = "{attacker} lurch{es} forward"
    result = render_pov(template, viewer=jared, attacker=jared, defender=goku)
    assert result == "You lurch forward"


def test_verb_es_conjugation_third_person(jared, goku, vegeta):
    """Verb with {es} after name gets 'es' suffix."""
    template = "{attacker} lurch{es} forward"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Jared lurches forward"


def test_irregular_verb_y_ies_you(jared, goku):
    """Irregular verb {y|ies} after You uses left form."""
    template = "{attacker} parr{y|ies} the blow"
    result = render_pov(template, viewer=jared, attacker=jared, defender=goku)
    assert result == "You parry the blow"


def test_irregular_verb_y_ies_third_person(jared, goku, vegeta):
    """Irregular verb {y|ies} after name uses right form."""
    template = "{attacker} parr{y|ies} the blow"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Jared parries the blow"


def test_pronoun_his_you(jared, goku):
    """{his} after You becomes 'your'."""
    template = "{attacker} raise{s} {his} fist"
    result = render_pov(template, viewer=jared, attacker=jared, defender=goku)
    assert result == "You raise your fist"


def test_pronoun_his_third_person(jared, goku, vegeta):
    """{his} after name becomes 'his'."""
    template = "{attacker} raise{s} {his} fist"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Jared raises his fist"


def test_pronoun_him_you(jared, goku):
    """{him} after You becomes 'you'."""
    template = "{attacker} brace{s} {him}self"
    result = render_pov(template, viewer=jared, attacker=jared, defender=goku)
    assert result == "You brace yourself"


def test_pronoun_him_third_person(jared, goku, vegeta):
    """{him} after name becomes 'him'."""
    template = "{attacker} brace{s} {him}self"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Jared braces himself"


def test_mixed_template_attacker_pov(jared, goku):
    """Complex template with multiple substitutions, attacker POV."""
    template = "{attacker} slam{s} {his} fist into {defender}"
    result = render_pov(template, viewer=jared, attacker=jared, defender=goku)
    assert result == "You slam your fist into Goku"


def test_mixed_template_defender_pov(jared, goku):
    """Complex template with multiple substitutions, defender POV."""
    template = "{attacker} slam{s} {his} fist into {defender}"
    result = render_pov(template, viewer=goku, attacker=jared, defender=goku)
    assert result == "Jared slams his fist into You"


def test_mixed_template_bystander_pov(jared, goku, vegeta):
    """Complex template with multiple substitutions, bystander POV."""
    template = "{attacker} slam{s} {his} fist into {defender}"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Jared slams his fist into Goku"


def test_defender_contextual_tags(jared, goku):
    """Contextual tags apply to defender when they precede them."""
    template = "{defender} brace{s} {him}self against {attacker}"
    result = render_pov(template, viewer=goku, attacker=jared, defender=goku)
    assert result == "You brace yourself against Jared"


def test_defender_contextual_third_person(jared, goku, vegeta):
    """Contextual tags apply to defender in third person."""
    template = "{defender} brace{s} {him}self against {attacker}"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Goku braces himself against Jared"


def test_plain_text_passthrough():
    """Template with no POV tags passes through unchanged."""
    template = "The battle rages on!"
    result = render_pov(template, viewer=None, attacker=None, defender=None)
    assert result == "The battle rages on!"


def test_you_capitalization_mid_sentence(jared, goku):
    """'You' is capitalized even when not at start of sentence."""
    template = "The blow strikes {defender} hard"
    result = render_pov(template, viewer=goku, attacker=jared, defender=goku)
    assert result == "The blow strikes You hard"


def test_multiple_entity_references(jared, goku):
    """Context switches between entities correctly."""
    template = "{attacker} throw{s} a punch at {defender}, but {defender} dodge{s} it"
    result = render_pov(template, viewer=goku, attacker=jared, defender=goku)
    assert result == "Jared throws a punch at You, but You dodge it"


def test_multiple_entity_references_attacker_pov(jared, goku):
    """Context switches correctly from attacker POV."""
    template = "{attacker} throw{s} a punch at {defender}, but {defender} dodg{es} it"
    result = render_pov(template, viewer=jared, attacker=jared, defender=goku)
    assert result == "You throw a punch at Goku, but Goku dodges it"


def test_you_capitalized_after_comma(jared, goku):
    """'You' stays capitalized after comma/conjunction."""
    template = "{attacker} strikes, and {defender} fall{s}"
    result = render_pov(template, viewer=goku, attacker=jared, defender=goku)
    assert result == "Jared strikes, and You fall"


def test_s_conjugation_after_ch(jared, goku, vegeta):
    """{s} after 'ch' should add 'es' for third person."""
    template = "{attacker} punch{s} {defender}"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Jared punches Goku"


def test_s_conjugation_after_sh(jared, goku, vegeta):
    """{s} after 'sh' should add 'es' for third person."""
    template = "{attacker} smash{s} into {defender}"
    result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku)
    assert result == "Jared smashes into Goku"


def test_s_conjugation_you_after_ch(jared, goku):
    """{s} should not add suffix for 'You' regardless of word ending."""
    template = "{attacker} punch{s} {defender}"
    result = render_pov(template, viewer=jared, attacker=jared, defender=goku)
    assert result == "You punch Goku"


def test_s_conjugation_at_template_start():
    """{s} at start of template should not crash when checking prev_text."""
    template = "{s}test"
    result = render_pov(template, viewer=None, attacker=None, defender=None)
    # Without entity, last_was_you defaults to False, so should add 's'
    assert result == "stest"
