package com.example.boidelov3.games.game89;

import org.junit.Test;
import static org.junit.Assert.*;

/**
 * Tests unitaires pour la classe Game89Player.
 * Couvre la gestion des joueurs et leurs statistiques de gorgées.
 */
public class Game89PlayerTest {

    @Test
    public void testConstructor_initializesWithName() {
        Game89Player player = new Game89Player("Alice");

        assertEquals("Player name should be Alice", "Alice", player.getName());
        assertEquals("Initial gorgées should be 0", 0, player.getTotalGorgees());
    }

    @Test
    public void testConstructor_withEmptyName() {
        Game89Player player = new Game89Player("");

        assertEquals("Player name should be empty", "", player.getName());
        assertEquals("Initial gorgées should be 0", 0, player.getTotalGorgees());
    }

    @Test
    public void testGetName_returnsCorrectName() {
        Game89Player player = new Game89Player("Bob");

        assertEquals("Player name should be Bob", "Bob", player.getName());
    }

    @Test
    public void testGetTotalGorgees_initialValue() {
        Game89Player player = new Game89Player("Charlie");

        assertEquals("Initial total gorgées should be 0", 0, player.getTotalGorgees());
    }

    @Test
    public void testAddGorgees_incrementsCount() {
        Game89Player player = new Game89Player("David");
        player.addGorgees(5);

        assertEquals("Total gorgées should be 5", 5, player.getTotalGorgees());
    }

    @Test
    public void testAddGorgees_multipleAdds() {
        Game89Player player = new Game89Player("Emma");
        player.addGorgees(3);
        player.addGorgees(2);
        player.addGorgees(4);

        assertEquals("Total gorgées should be 9", 9, player.getTotalGorgees());
    }

    @Test
    public void testAddGorgees_withZero_doesNotChange() {
        Game89Player player = new Game89Player("Frank");
        player.addGorgees(5);
        player.addGorgees(0);

        assertEquals("Total gorgées should remain 5", 5, player.getTotalGorgees());
    }

    @Test
    public void testAddGorgees_withNegativeValue_allowsNegative() {
        Game89Player player = new Game89Player("Grace");
        player.addGorgees(10);
        player.addGorgees(-3);

        assertEquals("Total gorgées should be 7", 7, player.getTotalGorgees());
    }

    @Test
    public void testAddGorgees_withLargeValue() {
        Game89Player player = new Game89Player("Henry");
        player.addGorgees(1000);

        assertEquals("Should handle large values", 1000, player.getTotalGorgees());
    }

    @Test
    public void testAddGorgees_canReachZero() {
        Game89Player player = new Game89Player("Iris");
        player.addGorgees(5);
        player.addGorgees(-5);

        assertEquals("Total gorgées should be 0", 0, player.getTotalGorgees());
    }

    @Test
    public void testAddGorgees_canGoNegative() {
        Game89Player player = new Game89Player("Jack");
        player.addGorgees(-10);

        assertEquals("Total gorgées should be -10", -10, player.getTotalGorgees());
    }

    @Test
    public void testToString_format() {
        Game89Player player = new Game89Player("Kate");
        player.addGorgees(7);

        String toString = player.toString();

        assertTrue("toString should contain player name", toString.contains("Kate"));
        assertTrue("toString should contain gorgée count", toString.contains("7"));
        assertTrue("toString should contain 'gorgées'", toString.contains("gorgées"));
    }

    @Test
    public void testToString_withZeroGorgees() {
        Game89Player player = new Game89Player("Leo");

        String toString = player.toString();

        assertTrue("toString should contain player name", toString.contains("Leo"));
        assertTrue("toString should contain '0'", toString.contains("0"));
    }

    @Test
    public void testToString_withSingleGorgee() {
        Game89Player player = new Game89Player("Mia");
        player.addGorgees(1);

        String toString = player.toString();

        assertTrue("toString should contain '1'", toString.contains("1"));
    }

    @Test
    public void testMultiplePlayers_haveIndependentStats() {
        Game89Player player1 = new Game89Player("Noah");
        Game89Player player2 = new Game89Player("Olivia");
        Game89Player player3 = new Game89Player("Peter");

        player1.addGorgees(5);
        player2.addGorgees(3);
        player3.addGorgees(8);

        assertEquals("Noah should have 5 gorgées", 5, player1.getTotalGorgees());
        assertEquals("Olivia should have 3 gorgées", 3, player2.getTotalGorgees());
        assertEquals("Peter should have 8 gorgées", 8, player3.getTotalGorgees());
    }

    @Test
    public void testSameNamePlayers_areDistinct() {
        Game89Player player1 = new Game89Player("Quinn");
        Game89Player player2 = new Game89Player("Quinn");

        player1.addGorgees(5);
        player2.addGorgees(3);

        assertNotEquals("Players with same name should have independent stats",
                player1.getTotalGorgees(), player2.getTotalGorgees());
    }

    @Test
    public void testAddGorgees_sequenceOfOperations() {
        Game89Player player = new Game89Player("Rachel");

        player.addGorgees(10);
        assertEquals("After first add: 10", 10, player.getTotalGorgees());

        player.addGorgees(-5);
        assertEquals("After second add: 5", 5, player.getTotalGorgees());

        player.addGorgees(0);
        assertEquals("After third add: 5", 5, player.getTotalGorgees());

        player.addGorgees(20);
        assertEquals("After fourth add: 25", 25, player.getTotalGorgees());

        player.addGorgees(-25);
        assertEquals("After fifth add: 0", 0, player.getTotalGorgees());
    }

    @Test
    public void testGetName_withSpecialCharacters() {
        Game89Player player = new Game89Player("José éàï");

        assertEquals("Should handle special characters", "José éàï", player.getName());
    }

    @Test
    public void testGetName_withNumbers() {
        Game89Player player = new Game89Player("Player123");

        assertEquals("Should handle numbers in name", "Player123", player.getName());
    }

    @Test
    public void testGetName_withSpaces() {
        Game89Player player = new Game89Player("Anna Marie");

        assertEquals("Should handle spaces in name", "Anna Marie", player.getName());
    }

    @Test
    public void testToString_formatConsistency() {
        Game89Player player = new Game89Player("Tom");
        player.addGorgees(42);

        String toString1 = player.toString();
        String toString2 = player.toString();

        assertEquals("toString should be consistent", toString1, toString2);
        assertTrue("Format should be 'name (count gorgées)'",
                toString1.matches(".+\\s\\(\\d+\\s[gG]org[eé]es\\)"));
    }

    @Test
    public void testAddGorgees_maxIntegerValue() {
        Game89Player player = new Game89Player("Uma");
        player.addGorgees(Integer.MAX_VALUE);

        assertEquals("Should handle MAX_VALUE", Integer.MAX_VALUE, player.getTotalGorgees());
    }

    @Test
    public void testToString_identifiesPlayer() {
        Game89Player player = new Game89Player("Victor");
        player.addGorgees(15);

        String toString = player.toString();

        assertTrue("toString should identify the player", toString.contains("Victor"));
        assertTrue("toString should show the count", toString.contains("15"));
    }

    @Test
    public void testPlayerState_persistsWithinSession() {
        Game89Player player = new Game89Player("Wendy");

        // Simulate game rounds
        player.addGorgees(2);  // Round 1
        player.addGorgees(3);  // Round 2
        player.addGorgees(1);  // Round 3
        player.addGorgees(4);  // Round 4

        assertEquals("Total after 4 rounds should be 10", 10, player.getTotalGorgees());
    }

    @Test
    public void testConstructor_withNullSafeBehavior() {
        // Test that constructor handles various string inputs
        Game89Player player1 = new Game89Player("A");
        Game89Player player2 = new Game89Player("VeryLongNameThatMightBeUsedInGame");

        assertEquals("Single character name", "A", player1.getName());
        assertEquals("Long name", "VeryLongNameThatMightBeUsedInGame", player2.getName());
    }

    @Test
    public void testAddGorgees_boundaryValues() {
        Game89Player player = new Game89Player("Xavier");

        player.addGorgees(1);
        assertEquals("Adding 1", 1, player.getTotalGorgees());

        player.addGorgees(-1);
        assertEquals("Adding -1", 0, player.getTotalGorgees());
    }
}
