// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 Sudoku Solver Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "SudokuSolver.h"
#include <iostream>
#include <chrono>

/**
 * @brief Demonstrates the Sudoku solver with example puzzles
 */
int main() {
    SudokuSolver solver;
    
    // Example puzzle 1 - Easy level
    int puzzle1[9][9] = {
        {5, 3, 0, 0, 7, 0, 0, 0, 0},
        {6, 0, 0, 1, 9, 5, 0, 0, 0},
        {0, 9, 8, 0, 0, 0, 0, 6, 0},
        {8, 0, 0, 0, 6, 0, 0, 0, 3},
        {4, 0, 0, 8, 0, 3, 0, 0, 1},
        {7, 0, 0, 0, 2, 0, 0, 0, 6},
        {0, 6, 0, 0, 0, 0, 2, 8, 0},
        {0, 0, 0, 4, 1, 9, 0, 0, 5},
        {0, 0, 0, 0, 8, 0, 0, 7, 9}
    };
    
    // Example puzzle 2 - Hard level
    int puzzle2[9][9] = {
        {0, 0, 0, 6, 0, 0, 4, 0, 0},
        {7, 0, 0, 0, 0, 3, 6, 0, 0},
        {0, 0, 0, 0, 9, 1, 0, 8, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 5, 0, 1, 8, 0, 0, 0, 3},
        {0, 0, 0, 3, 0, 6, 0, 4, 5},
        {0, 4, 0, 2, 0, 0, 0, 6, 0},
        {9, 0, 3, 0, 0, 0, 0, 0, 0},
        {0, 2, 0, 0, 0, 0, 1, 0, 0}
    };
    
    std::cout << "=== Sudoku Solver Demo ===" << std::endl;
    
    // Solve puzzle 1
    std::cout << "\n--- Puzzle 1 (Easy) ---" << std::endl;
    std::vector<std::vector<int>> grid1;
    solver.LoadPuzzle(grid1, puzzle1);
    
    std::cout << "Original puzzle:" << std::endl;
    solver.PrintGrid(grid1);
    
    auto start_time = std::chrono::high_resolution_clock::now();
    bool solved1 = solver.SolvePuzzle(grid1);
    auto end_time = std::chrono::high_resolution_clock::now();
    
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);
    
    if (solved1) {
        std::cout << "Solution found!" << std::endl;
        solver.PrintGrid(grid1);
        std::cout << "Solving time: " << duration.count() << " microseconds" << std::endl;
        std::cout << "Backtracks: " << solver.GetBacktrackCount() << std::endl;
    } else {
        std::cout << "No solution exists for this puzzle." << std::endl;
    }
    
    // Solve puzzle 2
    std::cout << "\n--- Puzzle 2 (Hard) ---" << std::endl;
    std::vector<std::vector<int>> grid2;
    solver.LoadPuzzle(grid2, puzzle2);
    
    std::cout << "Original puzzle:" << std::endl;
    solver.PrintGrid(grid2);
    
    start_time = std::chrono::high_resolution_clock::now();
    bool solved2 = solver.SolvePuzzle(grid2);
    end_time = std::chrono::high_resolution_clock::now();
    
    duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);
    
    if (solved2) {
        std::cout << "Solution found!" << std::endl;
        solver.PrintGrid(grid2);
        std::cout << "Solving time: " << duration.count() << " microseconds" << std::endl;
        std::cout << "Backtracks: " << solver.GetBacktrackCount() << std::endl;
    } else {
        std::cout << "No solution exists for this puzzle." << std::endl;
    }
    
    // Test with invalid puzzle
    std::cout << "\n--- Invalid Puzzle Test ---" << std::endl;
    int invalid_puzzle[9][9] = {
        {5, 5, 0, 0, 7, 0, 0, 0, 0},  // Two 5's in first row - invalid
        {6, 0, 0, 1, 9, 5, 0, 0, 0},
        {0, 9, 8, 0, 0, 0, 0, 6, 0},
        {8, 0, 0, 0, 6, 0, 0, 0, 3},
        {4, 0, 0, 8, 0, 3, 0, 0, 1},
        {7, 0, 0, 0, 2, 0, 0, 0, 6},
        {0, 6, 0, 0, 0, 0, 2, 8, 0},
        {0, 0, 0, 4, 1, 9, 0, 0, 5},
        {0, 0, 0, 0, 8, 0, 0, 7, 9}
    };
    
    std::vector<std::vector<int>> invalid_grid;
    solver.LoadPuzzle(invalid_grid, invalid_puzzle);
    
    std::cout << "Testing invalid puzzle (two 5's in first row):" << std::endl;
    solver.PrintGrid(invalid_grid);
    
    bool solved_invalid = solver.SolvePuzzle(invalid_grid);
    if (!solved_invalid) {
        std::cout << "Correctly identified as unsolvable puzzle." << std::endl;
    }
    
    std::cout << "\n=== Demo Complete ===" << std::endl;
    
    return 0;
}