package sudoku;

import org.junit.jupiter.api.Test;

import sudoku.core.Console;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Arrays;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class AppTest {

    /**
     * Test the creation of a Sudoku grid with a size of 16
     */
    @Test
    public void testExample() {
        // Simulate user input with proper line endings
        // First 1 is to select the int type of Symboles and after, Symboles are entered (1 to 16)
        String simulatedInput = "1\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n";
        System.setIn(new ByteArrayInputStream(simulatedInput.getBytes()));

        // Create a new Sudoku
        Sudoku sudoku = new Sudoku(16);
        sudoku.getGrille().askSetSymbolesPossibles();

        // Verify the symbols
        ArrayList<Symbole> expectedSymbols = new ArrayList<>(Arrays.asList(
                Symbole.of(1),
                Symbole.of(2),
                Symbole.of(3),
                Symbole.of(4),
                Symbole.of(5),
                Symbole.of(6),
                Symbole.of(7),
                Symbole.of(8),
                Symbole.of(9),
                Symbole.of(10),
                Symbole.of(11),
                Symbole.of(12),
                Symbole.of(13),
                Symbole.of(14),
                Symbole.of(15),
                Symbole.of(16)));
        assertEquals(expectedSymbols, sudoku.getGrille().getSymbolesPossibles());

        // Cleanup
        System.setIn(System.in);
    }

    @Test
    public void testContraintes() {
        // Create a new Sudoku
        Sudoku sudoku = new Sudoku(16);
        sudoku.getGrille().setSymbolesPossibles(new ArrayList<>(Arrays.asList(
                Symbole.of(1),
                Symbole.of(2),
                Symbole.of(3),
                Symbole.of(4),
                Symbole.of(5),
                Symbole.of(6),
                Symbole.of(7),
                Symbole.of(8),
                Symbole.of(9),
                Symbole.of(10),
                Symbole.of(11),
                Symbole.of(11),
                Symbole.of(12),
                Symbole.of(13),
                Symbole.of(14),
                Symbole.of(15),
                Symbole.of(16))));

        // Add constraints
        sudoku.ajouterContrainte(new ContrainteLigne());
        sudoku.ajouterContrainte(new ContrainteColonne());
        // sudoku.ajouterContrainte(new ContrainteBloc());

        // Fill the grid with valid symbols
        sudoku.getGrille().setCase(0, 0, Symbole.of(1));
        sudoku.getGrille().setCase(0, 1, Symbole.of(2));
        sudoku.getGrille().setCase(0, 2, Symbole.of(3));
        sudoku.getGrille().setCase(1, 0, Symbole.of(4));
        sudoku.getGrille().setCase(1, 1, Symbole.of(5));
        sudoku.getGrille().setCase(1, 2, Symbole.of(6));
        sudoku.getGrille().setCase(2, 0, Symbole.of(7));
        sudoku.getGrille().setCase(2, 1, Symbole.of(8));
        sudoku.getGrille().setCase(2, 2, Symbole.of(9));
        sudoku.getGrille().setCase(2, 8, Symbole.of(9));
        sudoku.getGrille().setCase(14, 2, Symbole.of(6));
        sudoku.getGrille().setCase(3, 3, Symbole.of(5));
        // sudoku.getGrille().setCase(2, 2, Symbole.of(13));
        // sudoku.getGrille().setCase(2, 2, Symbole.of(14));
        // sudoku.getGrille().setCase(2, 2, Symbole.of(15));

        // Create square blocks
        sudoku.getGrille().creerBlocCarre();

        System.out.println(sudoku.getGrille().toString());

        // Verify that the constraints are respected
        // assertTrue(sudoku.estValide(sudoku.getGrille().getCase(0, 0)));
        // assertTrue(sudoku.estValide(sudoku.getGrille().getCase(1, 1)));
        // assertTrue(sudoku.estValide(sudoku.getGrille().getCase(2, 2)));

        if (sudoku.verifierToutesContraintes()) {
            Console.successln("Toutes les contraintes sont respectées !");
        } else {
            Console.errorln("Au moins une contrainte n'est pas respectée.");
        }

        // Add a duplicate symbol in the same row
        // sudoku.getGrille().setCase(0, 3, Symbole.of(1));
        // assertFalse(sudoku.estValide(sudoku.getGrille().getCase(0, 3)));

        // Add a duplicate symbol in the same column
        // sudoku.getGrille().setCase(3, 0, Symbole.of(1));
        // assertFalse(sudoku.estValide(sudoku.getGrille().getCase(3, 0)));

        // Add a duplicate symbol in the same block
        // sudoku.getGrille().setCase(1, 1, Symbole.of(1));
        // assertFalse(sudoku.estValide(sudoku.getGrille().getCase(1, 1)));
    }
}