"""Griddle - A Waffle word puzzle game.

This game presents a 5x5 grid of letters where players need to swap letters
to form valid words horizontally and vertically. The goal is to match the
solution grid with the minimum number of swaps.

Color coding:
- GREEN [X]: Letter is in the correct position
- YELLOW (X): Letter is in the correct row or column but wrong position
- RED _X_: Letter is not in the correct row or column
- WHITE  X : Empty cell (underscore in the grid)

Players use letter indices (a-y, excluding g,i,q,s) to swap cells.
"""

import sys
import os
from file_utils import Grid, read_file, write_log, check_grid, print_log
from word_utils import print_grid, update_grid, swap_cells, check_swap, is_solved


def load_game(starter_file: str, solution_file: str) -> tuple[Grid, Grid]:
    """Load the starter and solution grids from files.

    Args:
        starter_file: Path to the starter grid file.
        solution_file: Path to the solution grid file.

    Returns:
        (starter_grid, solution_grid)

    Raises:
        ValueError: If either grid is invalid.
    """
    starter = read_file(starter_file)
    solution = read_file(solution_file)

    # Validate grids
    starter_check = check_grid(starter)
    solution_check = check_grid(solution)

    if starter_check != "valid":
        raise ValueError(f"Starter grid is invalid ({starter_check})")
    if solution_check != "valid":
        raise ValueError(f"Solution grid is invalid ({solution_check})")

    return starter, solution


def print_instructions() -> None:
    """Print game instructions."""
    print("\n" + "="*60)
    print("GRIDDLE - A WAFFLE LIKE WORD PUZZLE")
    print("="*60)
    print("GOAL: Swap letters to form valid words in all rows and columns.")
    print("COLOR CODE:")
    print("  [X] GREEN   - Letter is in the correct position")
    print("  (X) YELLOW  - Letter is in correct row/column, wrong position")
    print("  _X_ RED     - Letter is not in correct row/column")
    print("   _  WHITE   - Empty cell (underscore surrounded by spaces)")
    print("COMMANDS:")
    print("  <letter> <letter> - Swap two cells (e.g., 'a b')")
    # print("  hint              - Show number of correct letters")
    print("  quit              - Exit the game")
    print("LETTER INDICES (shown on right side of grid)")
    print("  Use letters a-y (excluding g,i,q,s) to reference cells")
    print("="*60 + "\n")


def game_loop(starter: Grid, solution: Grid) -> None:
    """Main game loop for Griddle.

    Args:
        starter: The starter grid.
        solution: The solution grid.
    """
    # Initialize game state
    current = starter.copy()
    swap_count = 0

    # Main game loop
    while True:
        # Validate and color the current grid
        colored_grid = update_grid(current, solution)
        # Check if swaps over limit
        if swap_count > 15:
            print("\nX You've exceeded the maximum number of swaps (15). Game over.\n")
            print_log()
            break
        # Print current grid
        print(f"\nSwaps made: {swap_count}")
        print_grid(colored_grid)
        # Check if solved
        if is_solved(current, solution):
            print("\n" + "🎉" * 30)
            print("CONGRATULATIONS! You solved the puzzle!")
            print(f"Total swaps: {swap_count}")
            print("🎉" * 30 + "\n")
            print_log()
            break
        # Get user command input
        user_input = input("\nEnter command (or 'quit' to exit): ").strip().lower()
        # Handle quit
        if user_input == "quit":
            print("\nThanks for playing! Come back soon.")
            print_log()
            break
        # Parse swap command
        parts = user_input.split()
        if len(parts) != 2:
            print("X Invalid input. Enter two letters separated by space (e.g., 'a b')")
            continue
        first, second = parts[0], parts[1]
        # Check if swap is valid
        check_result = check_swap(first, second)
        if check_result != "valid":
            if check_result == "out of range":
                print("X Invalid swap: Letters must be a-w (excluding g,i,q,s)")
            else:
                print(f"X Invalid swap: {check_result}")
            continue
        # Perform swap
        new_grid = swap_cells(first, second, current)
        if isinstance(new_grid, str):
            print(f"X Swap failed: {new_grid}")
            continue
        # Update game state
        current = new_grid
        swap_count += 1
        # Log the swap
        write_log((first, second))
        print(f"OK-Swapped {first} <-> {second}")


def play_game(starter_file: str = "starter.txt", solution_file: str = "solution.txt") -> None:
    """Load the game files, print the instructions, and run the game loop.

    Args:
        starter_file: Path to starter grid file.
        solution_file: Path to solution grid file.
    """
    # If relative paths, make them relative to this module's directory
    if not os.path.isabs(starter_file):
        starter_file = os.path.join(os.path.dirname(__file__), starter_file)
    if not os.path.isabs(solution_file):
        solution_file = os.path.join(os.path.dirname(__file__), solution_file)

    # Load game
    starter, solution = load_game(starter_file, solution_file)
    if starter is None or solution is None:
        return

    # Print instructions
    print_instructions()
    game_loop(starter, solution)


if __name__ == "__main__":
    # Reset the log.txt file
    log_path = os.path.join(os.path.dirname(__file__), "log.txt")
    with open(log_path, "w", encoding="utf-8") as fh:
        fh.write("")  # Clear contents
    # Check for command line arguments for custom filenames
    if len(sys.argv) == 3:
        starter_file = sys.argv[1]
        solution_file = sys.argv[2]
        play_game(starter_file, solution_file)
    elif len(sys.argv) == 1:
        # Use default files
        play_game()
    else:
        print("Usage: python griddle.py [starter_file solution_file]")
        print("  or: python griddle.py (uses default starter.txt and solution.txt)")
        sys.exit(1)
