"""Главный файл программы"""

import sys
from pathlib import Path

from builders import TextFileMazeBuilder
from solver import MazeSolver
from strategies import BFSStrategy, DFSStrategy, AStarStrategy
from visualization import ConsoleView
from commands import MoveCommand
from models import Player
from experiments import ExperimentRunner


def create_test_maze_files():
    """Создание тестовых лабиринтов"""
    Path("mazes").mkdir(exist_ok=True)
    
    # Лабиринт 1: Маленький запутанный (10×10)
    small_maze = [
        "##########",
        "#S       #",
        "# ####### #",
        "#       # #",
        "##### # # #",
        "#     #   #",
        "# ### ### #",
        "#   #     #",
        "#   #### E#",
        "##########"
    ]
    
    # Лабиринт 2: Простой прямой путь (10×10)
    simple_maze = [
        "##########",
        "#S       #",
        "#        #",
        "#        #",
        "#        #",
        "#        #",
        "#        #",
        "#        #",
        "#       E#",
        "##########"
    ]
    
    # Лабиринт 3: Без выхода (10×10)
    no_exit_maze = [
        "##########",
        "#S       #",
        "# ####### #",
        "#       # #",
        "##### # # #",
        "#     #   #",
        "# ### ### #",
        "#   #     #",
        "#   #######",
        "##########"
    ]
    
    # Лабиринт 4: Спиральный
    spiral_maze = [
        "##########",
        "#S       #",
        "# ####### #",
        "# #     # #",
        "# # ### # #",
        "# # #   # #",
        "# # ### # #",
        "# #     # #",
        "# #######E#",
        "##########"
    ]
    
    with open("mazes/small_maze.txt", "w", encoding="utf-8") as f:
        f.write('\n'.join(small_maze))
    with open("mazes/simple_maze.txt", "w", encoding="utf-8") as f:
        f.write('\n'.join(simple_maze))
    with open("mazes/no_exit_maze.txt", "w", encoding="utf-8") as f:
        f.write('\n'.join(no_exit_maze))
    with open("mazes/spiral_maze.txt", "w", encoding="utf-8") as f:
        f.write('\n'.join(spiral_maze))
    
    print("Созданы тестовые лабиринты в папке mazes/")


def interactive_mode():
    """Интерактивный режим с ручным управлением"""
    print("\n" + "=" * 50)
    print("Интерактивный режим")
    print("=" * 50)
    
    builder = TextFileMazeBuilder()
    view = ConsoleView()
    
    maze_file = input("Введите путь к файлу (по умолчанию: mazes/small_maze.txt): ")
    if not maze_file:
        maze_file = "mazes/small_maze.txt"
    
    try:
        maze = builder.build_from_file(maze_file)
        view.update("maze_loaded", {"maze": maze})
    except Exception as e:
        print(f"Ошибка: {e}")
        return
    
    print("\nСтратегии:")
    print("1. BFS (кратчайший путь)")
    print("2. DFS (быстрый, но не оптимальный)")
    print("3. A* (оптимальный с эвристикой)")
    
    choice = input("Выберите (1-3): ")
    strategies = {
        "1": BFSStrategy(), 
        "2": DFSStrategy(), 
        "3": AStarStrategy()
    }
    strategy = strategies.get(choice, BFSStrategy())
    
    print(f"\nВыбрана стратегия: {strategy.name}")
    
    solver = MazeSolver(maze, strategy)
    path, stats = solver.solve()
    
    if path:
        view.update("path_found", {"path": path, "maze": maze})
        print(f"\n{stats}")
    else:
        view.update("path_not_found", {})
        print("Путь не найден!")
    
    # Демонстрация Command (пошаговое движение)
    print("\n" + "-" * 30)
    print("Демонстрация паттерна Command (пошаговое движение)")
    print("-" * 30)
    
    if path:
        player = Player(maze.start)
        print("\nПошаговое движение по найденному пути (Enter - следующий шаг, q - выход):")
        
        for i, cell in enumerate(path[1:], 1):
            cmd = MoveCommand(player, cell)
            cmd.execute()
            view.render(maze, player.current_cell, path[:i+1])
            print(f"Шаг {i}/{len(path)-1}")
            
            key = input("Нажмите Enter для продолжения или 'q' для выхода: ")
            if key.lower() == 'q':
                break
        
        if player.current_cell == maze.exit:
            print("\n🎉 Вы достигли выхода!")


def experiment_mode():
    """Экспериментальный режим сравнения алгоритмов"""
    print("\n" + "=" * 50)
    print("Экспериментальное сравнение алгоритмов")
    print("=" * 50)
    
    create_test_maze_files()
    
    runner = ExperimentRunner()
    maze_files = [
        "mazes/small_maze.txt",
        "mazes/simple_maze.txt", 
        "mazes/no_exit_maze.txt",
        "mazes/spiral_maze.txt"
    ]
    
    results = runner.run_all_experiments(maze_files, runs=10)
    
    print("\n" + "=" * 50)
    print("Сводная таблица результатов:")
    print("=" * 50)
    print(f"{'Лабиринт':<15} {'Стратегия':<10} {'Ср. время (мс)':<15} {'Длина пути':<12} {'Найден':<8}")
    print("-" * 65)
    
    for r in results:
        status = "✓" if r['path_found'] else "✗"
        print(f"{r['maze']:<15} {r['strategy']:<10} {r['avg_time_ms']:<15.3f} {r['path_length']:<12} {status:<8}")


def main():
    print("\n" + "=" * 50)
    print("Лабораторная работа: Поиск выхода из лабиринта")
    print("Паттерны: Builder, Strategy, Observer, Command")
    print("=" * 50)
    
    print("\n1. Интерактивный режим (ручное управление)")
    print("2. Экспериментальный режим (сравнение алгоритмов)")
    
    choice = input("\nВыберите (1-2): ")
    
    if choice == "1":
        interactive_mode()
    elif choice == "2":
        experiment_mode()
    else:
        print("Неверный выбор!")


if __name__ == "__main__":
    main()