import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

/**
 * La classe SudokuGame étend la classe SudokuUI et représente une application de jeu de Sudoku avec des fonctionnalités supplémentaires telles que le chargement de grilles et la résolution automatique.
 */
public class SudokuGame extends SudokuUI {

    /**
     * Constructeur de la classe SudokuGame.
     *
     * @param sudoku La grille de Sudoku à utiliser pour le jeu.
     */
    public SudokuGame(Sudoku sudoku) {
        super(sudoku);
        createAdditionalButtons();
    }

    /**
     * Méthode pour obtenir le texte du titre de l'interface utilisateur.
     *
     * @return Le texte du titre.
     */
    @Override
    protected String getTitleText() {
        return "Sudoku Game";
    }

    /**
     * Méthode pour créer les boutons de chargement et de résolution et redimensionner la fenêtre.
     */
    protected void createAdditionalButtons() {
        createLoadButton();
        createSolveButton();
        pack(); // Redimensionner la fenêtre pour s'adapter aux nouveaux boutons
    }

    /**
     * Méthode pour créer le bouton de résolution.
     */
    private void createSolveButton() {
        JButton solveButton = new JButton("Résoudre (Automatique)");
        solveButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                long startTime = System.nanoTime(); // Temps de début de la résolution

                SudokuSolver solver = new SudokuSolver(); // Créez une instance de SudokuSolver
                Grid solvedGrid = new Grid(); // Créez une nouvelle grille pour stocker la solution
                solvedGrid.copyFrom(sudoku.getGrid()); // Copiez la grille actuelle de Sudoku

                // Résolvez la grille
                if (solver.solve(solvedGrid)) {
                    long endTime = System.nanoTime(); // Temps de fin de la résolution
                    long duration = (endTime - startTime) / 1_000_000; // Conversion de nanosecondes en millisecondes

                    // Si une solution est trouvée, mettez à jour la grille Sudoku avec la solution
                    sudoku.getGrid().copyFrom(solvedGrid);
                    updateGrid();
                    JOptionPane.showMessageDialog(null, "La grille a été résolue en " + duration + " millisecondes.");
                    checkGameCompletion(); // Vérifiez si le jeu est terminé après la résolution
                } else {
                    // Sinon, affichez un message indiquant que la grille est insoluble
                    JOptionPane.showMessageDialog(null, "La grille est insoluble.");
                }
            }
        });

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(solveButton);
        add(buttonPanel, BorderLayout.SOUTH);
    }

    /**
     * Méthode pour créer le bouton de chargement.
     */
    private void createLoadButton() {
        JButton loadButton = new JButton("Charger");
        loadButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser();
                FileNameExtensionFilter filter = new FileNameExtensionFilter("Fichiers de grille Sudoku (*.gri)", "gri");
                fileChooser.setFileFilter(filter);
                int returnValue = fileChooser.showOpenDialog(null);
                if (returnValue == JFileChooser.APPROVE_OPTION) {
                    File selectedFile = fileChooser.getSelectedFile();
                    sudoku.loadGridFromFile(selectedFile.getAbsolutePath());
                    updateGrid();
                }
            }
        });

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(loadButton);
        add(buttonPanel, BorderLayout.NORTH);
    }

    /**
     * Méthode pour mettre à jour les valeurs des boutons de la grille après un chargement ou une résolution.
     */
    private void updateGrid() {
        Grid grid = sudoku.getGrid();
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                int value = grid.getCell(row, col).getValue();
                buttons[row][col].setText(value == 0 ? "" : String.valueOf(value));
                buttons[row][col].setEnabled(value == 0); // Désactive les boutons pour les cellules déjà remplies
            }
        }
    }

    /**
     * Méthode pour vérifier si la grille est complètement remplie et si la solution est correcte.
     * Affiche une alerte si la grille est résolue correctement.
     */
    private void checkGameCompletion() {
        Grid grid = sudoku.getGrid();
        boolean isFull = true;
        boolean hasErrors = false;

        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                int value = grid.getCell(row, col).getValue();
                if (value == 0) {
                    isFull = false;
                } else if (!isValidMove(grid, row, col, value)) {
                    hasErrors = true;
                }
            }
        }

        if (isFull && !hasErrors) {
            JOptionPane.showMessageDialog(null, "Félicitations ! Vous avez résolu la grille avec succès !");
        }
    }

    /**
     * Vérifie si le placement d'un nombre dans une cellule est sûr.
     *
     * @param grid La grille de Sudoku.
     * @param row  L'indice de ligne de la cellule.
     * @param col  L'indice de colonne de la cellule.
     * @param num  Le nombre à vérifier.
     * @return True si le placement est sûr, False sinon.
     */
    private boolean isValidMove(Grid grid, int row, int col, int num) {
        // Votre logique de validation ici
        return false;
    }

    /**
     * Méthode principale pour démarrer le jeu de Sudoku.
     *
     * @param args Les arguments de la ligne de commande (non utilisés).
     */
    public static void main(String[] args) {
        Sudoku sudoku = new Sudoku();
        new SudokuGame(sudoku);
    }
}