package sudoku.solver;

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

import java.util.List;

import org.junit.jupiter.api.Test;

import gui.constants.Symbols;
import sudoku.io.SudokuPrinter;
import sudoku.io.SudokuSerializer;
import sudoku.structure.Cell;
import sudoku.structure.MultiDoku;
import sudoku.structure.Sudoku;
import sudoku.structure.SudokuFactory;

class SolverTest {

	@Test
	void solveTest() {
		MultiDoku dokuToTest = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
		MultiDoku dokuResult = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);

		Sudoku sudokuToTest = dokuToTest.getSubGrid(0);
		Sudoku sudokuResult = dokuResult.getSubGrid(0);

		int ns = Cell.NOSYMBOL;
		List<Integer> immutableCells = List.of(ns, ns, 0, ns, ns, 2, 8, ns, 1,
				ns, 3, ns, ns, 5, 6, 7, ns, ns,
				ns, ns, ns, 8, ns, 7, ns, ns, 6,
				0, ns, 1, ns, ns, ns, ns, ns, ns,
				4, 8, 7, 5, 1, ns, 6, ns, ns,
				6, ns, 3, 2, ns, ns, ns, 8, 0,
				ns, ns, 6, ns, ns, 8, ns, 7, 5,
				8, 0, ns, 7, ns, 5, 2, ns, 3,
				5, ns, ns, ns, 3, 1, 0, ns, ns);

		assert (sudokuToTest.setImmutableCellsSymbol(immutableCells));

		//SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
		SudokuPrinter.printMultiDoku(dokuToTest, 3, 3, Symbols.Numbers);

		List<Integer> correctCells = List.of(7, 6, 0, 3, 4, 2, 8, 5, 1,
				2, 3, 8, 1, 5, 6, 7, 0, 4,
				1, 4, 5, 8, 0, 7, 3, 2, 6,
				0, 2, 1, 6, 8, 3, 5, 4, 7,
				4, 8, 7, 5, 1, 0, 6, 3, 2,
				6, 5, 3, 2, 7, 4, 1, 8, 0,
				3, 1, 6, 0, 2, 8, 4, 7, 5,
				8, 0, 4, 7, 6, 5, 2, 1, 3,
				5, 7, 2, 4, 3, 1, 0, 6, 8);

		sudokuResult.setCellsSymbol(correctCells);

		System.out.println("\n****************************Doku Control\n");
		SudokuPrinter.printRectangleSudoku(sudokuResult, 3, 3, Symbols.Russian);

		assert (dokuResult.isSolved());

		new RandomSolver().solve(dokuToTest);

		System.out.println("\n****************************\nDoku solved");
		//SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
		SudokuPrinter.printMultiDoku(dokuToTest, 3, 3, Symbols.Emojis);

		assert (dokuToTest.isSolved());

		for (Cell cell : sudokuToTest.getCells()) {
			cell.setImmutable();
		}

		for (Cell cell : sudokuResult.getCells()) {
			cell.setImmutable();
		}

		assertEquals(SudokuSerializer.serializeSudoku(dokuResult).toString(),
				SudokuSerializer.serializeSudoku(dokuToTest).toString());

		MultiDoku dokuToTest2 = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
		Sudoku sudokuToTest2 = dokuToTest2.getSubGrid(0);

		List<Integer> immutableCells2 = List.of(ns, ns, 0, ns, ns, 2, 8, ns, 1,
				1, 3, ns, ns, 5, 6, 7, ns, ns,
				ns, ns, ns, 8, ns, 7, ns, ns, 6,
				0, ns, 1, ns, ns, ns, ns, ns, ns,
				4, 8, 7, 5, 1, ns, 6, ns, ns,
				6, ns, 3, 2, ns, ns, ns, 8, 0,
				ns, ns, 6, ns, ns, 8, ns, 7, 5,
				8, 0, ns, 7, ns, 5, 2, ns, 3,
				5, ns, ns, ns, 3, 1, 0, ns, ns);
		sudokuToTest2.setImmutableCellsSymbol(immutableCells2);

		boolean isSolved = new RandomSolver().solve(dokuToTest2);

		assert (!isSolved);

		MultiDoku dokuToTest3 = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);

		new RandomSolver().solve(dokuToTest3);

		//SudokuPrinter.printRectangleSudoku(dokuToTest3.getSubGrid(0), 3, 3);
		SudokuPrinter.printMultiDoku(dokuToTest3, 3, 3, Symbols.Letters);
	}
}