package com.example.boidelov3.data;

import android.os.Parcel;

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

/**
 * Tests unitaires pour la classe PlayerStats.
 * Couvre les statistiques de joueurs, les opérations arithmétiques et Parcelable.
 */
public class PlayerStatsTest {

    private PlayerStats playerStats;
    private static final String TEST_PLAYER_NAME = "Alice";

    @Before
    public void setUp() {
        playerStats = new PlayerStats(TEST_PLAYER_NAME);
    }

    @Test
    public void testConstructor_initializesWithZeroStats() {
        assertEquals("Player name should match", TEST_PLAYER_NAME, playerStats.getPlayerName());
        assertEquals("Initial gorgeesBuves should be 0", 0, playerStats.getGorgeesBuves());
        assertEquals("Initial gorgeesDistribuees should be 0", 0, playerStats.getGorgeesDistribuees());
        assertEquals("Initial total should be 0", 0, playerStats.getTotalGorgees());
    }

    @Test
    public void testGetPlayerName_returnsCorrectName() {
        assertEquals("Player name should be Alice", TEST_PLAYER_NAME, playerStats.getPlayerName());
    }

    @Test
    public void testGetGorgeesBuves_initialValue() {
        assertEquals("Initial gorgeesBuves should be 0", 0, playerStats.getGorgeesBuves());
    }

    @Test
    public void testAddGorgeesBuves_incrementsCount() {
        playerStats.addGorgeesBuves(5);
        assertEquals("GorgeesBuves should be 5", 5, playerStats.getGorgeesBuves());

        playerStats.addGorgeesBuves(3);
        assertEquals("GorgeesBuves should be 8", 8, playerStats.getGorgeesBuves());
    }

    @Test
    public void testAddGorgeesBuves_withZero_doesNotChange() {
        playerStats.addGorgeesBuves(5);
        playerStats.addGorgeesBuves(0);
        assertEquals("GorgeesBuves should remain 5", 5, playerStats.getGorgeesBuves());
    }

    @Test
    public void testAddGorgeesBuves_withNegativeValue_allowsNegative() {
        playerStats.addGorgeesBuves(5);
        playerStats.addGorgeesBuves(-2);
        assertEquals("GorgeesBuves should be 3", 3, playerStats.getGorgeesBuves());
    }

    @Test
    public void testGetGorgeesDistribuees_initialValue() {
        assertEquals("Initial gorgeesDistribuees should be 0", 0, playerStats.getGorgeesDistribuees());
    }

    @Test
    public void testAddGorgeesDistribuees_incrementsCount() {
        playerStats.addGorgeesDistribuees(7);
        assertEquals("GorgeesDistribuees should be 7", 7, playerStats.getGorgeesDistribuees());

        playerStats.addGorgeesDistribuees(2);
        assertEquals("GorgeesDistribuees should be 9", 9, playerStats.getGorgeesDistribuees());
    }

    @Test
    public void testAddGorgeesDistribuees_withZero_doesNotChange() {
        playerStats.addGorgeesDistribuees(10);
        playerStats.addGorgeesDistribuees(0);
        assertEquals("GorgeesDistribuees should remain 10", 10, playerStats.getGorgeesDistribuees());
    }

    @Test
    public void testGetTotalGorgees_withOnlyBuves() {
        playerStats.addGorgeesBuves(5);
        assertEquals("Total should be 5", 5, playerStats.getTotalGorgees());
    }

    @Test
    public void testGetTotalGorgees_withOnlyDistribuees() {
        playerStats.addGorgeesDistribuees(3);
        assertEquals("Total should be 3", 3, playerStats.getTotalGorgees());
    }

    @Test
    public void testGetTotalGorgees_withBoth() {
        playerStats.addGorgeesBuves(5);
        playerStats.addGorgeesDistribuees(3);
        assertEquals("Total should be 8", 8, playerStats.getTotalGorgees());
    }

    @Test
    public void testGetTotalGorgees_withZeros() {
        assertEquals("Total should be 0 when no stats", 0, playerStats.getTotalGorgees());
    }

    @Test
    public void testGetTotalGorgees_afterMultipleOperations() {
        playerStats.addGorgeesBuves(10);
        playerStats.addGorgeesDistribuees(5);
        playerStats.addGorgeesBuves(3);
        playerStats.addGorgeesDistribuees(2);

        assertEquals("Total should be 20", 20, playerStats.getTotalGorgees());
        assertEquals("GorgeesBuves should be 13", 13, playerStats.getGorgeesBuves());
        assertEquals("GorgeesDistribuees should be 7", 7, playerStats.getGorgeesDistribuees());
    }

    @Test
    public void testParcelable_CREATOR_notNull() {
        assertNotNull("CREATOR should not be null", PlayerStats.CREATOR);
    }

    @Test
    public void testParcelable_writeAndRead() {
        try {
            playerStats.addGorgeesBuves(15);
            playerStats.addGorgeesDistribuees(8);

            Parcel parcel = Parcel.obtain();
            playerStats.writeToParcel(parcel, 0);
            parcel.setDataPosition(0);

            PlayerStats restored = PlayerStats.CREATOR.createFromParcel(parcel);

            assertEquals("Player name should match", TEST_PLAYER_NAME, restored.getPlayerName());
            assertEquals("GorgeesBuves should match", 15, restored.getGorgeesBuves());
            assertEquals("GorgeesDistribuees should match", 8, restored.getGorgeesDistribuees());
            assertEquals("Total should match", 23, restored.getTotalGorgees());
        } catch (RuntimeException e) {
            // Parcel requires Android environment, skip in unit tests
            org.junit.Assume.assumeNoException("Skipping Parcel test in non-Android environment", e);
        }
    }

    @Test
    public void testParcelable_newArray() {
        PlayerStats[] array = PlayerStats.CREATOR.newArray(5);
        assertEquals("Array length should be 5", 5, array.length);
        assertNotNull("Array elements should not be null", array);
        for (PlayerStats stats : array) {
            assertNull("Array elements should be null initially", stats);
        }
    }

    @Test
    public void testDescribeContents() {
        assertEquals("describeContents should return 0", 0, playerStats.describeContents());
    }

    @Test
    public void testParcelable_withZeroStats() {
        try {
            Parcel parcel = Parcel.obtain();
            playerStats.writeToParcel(parcel, 0);
            parcel.setDataPosition(0);

            PlayerStats restored = PlayerStats.CREATOR.createFromParcel(parcel);

            assertEquals("Player name should match", TEST_PLAYER_NAME, restored.getPlayerName());
            assertEquals("GorgeesBuves should be 0", 0, restored.getGorgeesBuves());
            assertEquals("GorgeesDistribuees should be 0", 0, restored.getGorgeesDistribuees());
        } catch (RuntimeException e) {
            // Parcel requires Android environment, skip in unit tests
            org.junit.Assume.assumeNoException("Skipping Parcel test in non-Android environment", e);
        }
    }

    @Test
    public void testMultiplePlayers_haveIndependentStats() {
        PlayerStats player1 = new PlayerStats("Alice");
        PlayerStats player2 = new PlayerStats("Bob");

        player1.addGorgeesBuves(5);
        player2.addGorgeesBuves(3);
        player1.addGorgeesDistribuees(2);
        player2.addGorgeesDistribuees(4);

        assertEquals("Alice stats should be independent", 7, player1.getTotalGorgees());
        assertEquals("Bob stats should be independent", 7, player2.getTotalGorgees());
        assertEquals("Alice gorgeesBuves should be 5", 5, player1.getGorgeesBuves());
        assertEquals("Bob gorgeesBuves should be 3", 3, player2.getGorgeesBuves());
    }

    @Test
    public void testLargeValues() {
        playerStats.addGorgeesBuves(1000);
        playerStats.addGorgeesDistribuees(500);

        assertEquals("Should handle large values", 1500, playerStats.getTotalGorgees());
    }

    @Test
    public void testConstructor_withDifferentNames() {
        PlayerStats alice = new PlayerStats("Alice");
        PlayerStats bob = new PlayerStats("Bob");
        PlayerStats charlie = new PlayerStats("Charlie");

        assertEquals("Alice", alice.getPlayerName());
        assertEquals("Bob", bob.getPlayerName());
        assertEquals("Charlie", charlie.getPlayerName());
    }

    @Test
    public void testStatsDoNotInterfere() {
        playerStats.addGorgeesBuves(10);
        assertEquals(10, playerStats.getGorgeesBuves());
        assertEquals(0, playerStats.getGorgeesDistribuees());

        playerStats.addGorgeesDistribuees(5);
        assertEquals(10, playerStats.getGorgeesBuves()); // Should not change
        assertEquals(5, playerStats.getGorgeesDistribuees());
    }
}
