import os
import csv
from datetime import datetime
from maze_model import Maze
from maze_builder import TextFileMazeBuilder
from pathfinding_strategies import BFSStrategy, DFSStrategy, AStarStrategy
from maze_solver import MazeSolver


def get_maze_file():
    maze_files = [f for f in os.listdir('.') if f.endswith('.txt') and f != 'experiment_results.csv']
    
    if not maze_files:
        print("\nНет файлов лабиринтов! Поместите файлы labirint1.txt и т.д. в папку.")
        exit(1)
    
    print("\nДоступные файлы лабиринтов:")
    for i, f in enumerate(maze_files, 1):
        print(f"   {i}. {f}")
    
    while True:
        choice = input(f"\nВыберите файл (1-{len(maze_files)}): ").strip()
        try:
            idx = int(choice) - 1
            if 0 <= idx < len(maze_files):
                return maze_files[idx]
        except ValueError:
            pass
        print(f"Неверный выбор. Введите число от 1 до {len(maze_files)}")


def display_maze_with_path(maze: Maze, path=None):
    print("\n+" + "-" * maze.width + "+")
    
    for y in range(maze.height):
        row = "|"
        for x in range(maze.width):
            cell = maze.get_cell(x, y)
            if cell == maze.start_cell:
                row += "S"
            elif cell == maze.exit_cell:
                row += "E"
            elif path and cell in path:
                row += "."
            elif cell.is_wall:
                row += "#"
            else:
                row += " "
        row += "|"
        print(row)
    
    print("+" + "-" * maze.width + "+")


def save_to_csv(maze_name: str, algorithm_name: str, time_ms: float, path_length: int, path_found: bool, maze_size: str):
    csv_filename = "experiment_results.csv"
    
    file_exists = os.path.exists(csv_filename)
    
    with open(csv_filename, 'a', newline='', encoding='utf-8-sig') as f:
        writer = csv.writer(f)
        
        if not file_exists:
            writer.writerow(['лабиринт', 'стратегия', 'время_мс', 'длина_пути', 'путь_найден', 'размер', 'дата_время'])
        
        writer.writerow([
            maze_name,
            algorithm_name,
            round(time_ms, 3),
            path_length,
            'Да' if path_found else 'Нет',
            maze_size,
            datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        ])
    
    print(f"Результат сохранён в {csv_filename}")


def print_all_results():
    csv_filename = "experiment_results.csv"

    with open(csv_filename, 'r', encoding='utf-8-sig') as f:
        reader = csv.reader(f)
        headers = next(reader)
        print(f"{headers[0]:<25} {headers[1]:<22} {headers[2]:<10} {headers[3]:<10} {headers[4]:<8} {headers[5]:<10}")
        for row in reader:
            print(f"{row[0]:<25} {row[1]:<22} {row[2]:<10} {row[3]:<10} {row[4]:<8} {row[5]:<10}")


def main():
    filename = get_maze_file()
    
    try:
        builder = TextFileMazeBuilder()
        maze = builder.build_from_file(filename)
        
        maze_name = filename.replace('.txt', '')
        maze_size = f"{maze.width}x{maze.height}"
        
        print(f"\nЛабиринт загружен из файла: {filename}")
        print(f"   Размер: {maze_size}")
        print(f"   Старт: ({maze.start_cell.x}, {maze.start_cell.y})")
        print(f"   Выход: ({maze.exit_cell.x}, {maze.exit_cell.y})")
        
    except FileNotFoundError:
        print(f"\nФайл '{filename}' не найден!")
        return
    except ValueError as e:
        print(f"\nОшибка в файле лабиринта: {e}")
        return
    
    print("\nЗагруженный лабиринт:")
    maze.display()
    
    print("ВЫБОР АЛГОРИТМА ПОИСКА")
    print("1. BFS (Поиск в ширину)")
    print("2. DFS (Поиск в глубину)")
    print("3. A* (A-Star)")

    
    choice = input("\nВыберите алгоритм (1-3): ").strip()
    

    if choice == '1':
        strategy = BFSStrategy()
    elif choice == '2':
        strategy = DFSStrategy()
    elif choice == '3':
        strategy = AStarStrategy()
    else:
        print("Неверный выбор!")
        return
    

    solver = MazeSolver(maze, strategy)
    
    path, stats = solver.solve_with_stats()
    
    print(stats.detailed_report())
    
    if path:
        print("\nЛабиринт с найденным путём (точки):")
        display_maze_with_path(maze, path)
    else:
        print("Путь не найден!")
    
    # Сохраняем результат в CSV
    save_to_csv(
        maze_name=maze_name,
        algorithm_name=stats.algorithm_name,
        time_ms=stats.execution_time_ms,
        path_length=stats.path_length,
        path_found=stats.path_found,
        maze_size=maze_size
    )
    
    print("\nПрограмма завершена!")


if __name__ == "__main__":
    main()