# main.py
import csv
import os
import tempfile
from maze import Maze
from builder import TextFileMazeBuilder
from strategies import BFSStrategy, DFSStrategy, AStarStrategy
from solver import MazeSolver
from visualizer import ConsoleView

def demo():
    sample = """#######
#S    #
# ### #
#   # #
# # # #
#   E #
#######"""
    with open("maze_sample.txt", "w") as f:
        f.write(sample)

    builder = TextFileMazeBuilder()
    maze = builder.build_from_file("maze_sample.txt")
    print("Загруженный лабиринт:")
    ConsoleView.render(maze)

    strategies = {
        "BFS": BFSStrategy(),
        "DFS": DFSStrategy(),
        "A*": AStarStrategy()
    }

    for name, strat in strategies.items():
        solver = MazeSolver(maze, strat)
        stats = solver.solve()
        print(f"\n{name}: время = {stats.time_ms:.3f} мс, посещено = {stats.visited_cells}, длина пути = {stats.path_length}")
        ConsoleView.render(maze, stats.path)

def run_experiments():

    builder = TextFileMazeBuilder()

    def make_maze_from_str(s):
        with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
            f.write(s)
            name = f.name
        maze = builder.build_from_file(name)
        os.unlink(name)
        return maze

    # 1 10x10
    simple = """##########
#S       #
# ### ####
#   #   E#
##########"""
    # 2 20x20 с тупиками
    medium = """####################
#S                 #
# ### ########### #
#   # #       #   #
# ### # ### # # ###
#     #   #   #   #
##################E#"""

    mazes = {
        "simple_10x10": make_maze_from_str(simple),
        "medium_20x20": make_maze_from_str(medium)
    }

    # 3.  50x50 
    empty_lines = []
    for y in range(50):
        row = []
        for x in range(50):
            if x == 0 and y == 0:
                row.append('S')
            elif x == 49 and y == 49:
                row.append('E')
            else:
                row.append(' ')
        empty_lines.append(''.join(row))
    empty_str = '\n'.join(empty_lines)
    mazes["empty_50x50"] = make_maze_from_str(empty_str)

    # 4. Лабиринт без выхода (заменяем 'E' на '#', чтобы выхода не было)
    no_exit_str = empty_str.replace('E', '#')
    with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
        f.write(no_exit_str)
        name = f.name
    # Строим лабиринт без проверки на наличие выхода
    maze_no_exit = builder.build_from_file(name, require_exit=False)
    os.unlink(name)
    mazes["no_exit"] = maze_no_exit

    # Стратегии
    strategies = {
        "BFS": BFSStrategy(),
        "DFS": DFSStrategy(),
        "A*": AStarStrategy()
    }

    results = []
    for maze_name, maze in mazes.items():
        for strat_name, strat in strategies.items():
            times = []
            visiteds = []
            lengths = []
            for _ in range(5):  # 5 запусков для усреднения
                solver = MazeSolver(maze, strat)
                stats = solver.solve()
                times.append(stats.time_ms)
                visiteds.append(stats.visited_cells)
                lengths.append(stats.path_length)
            avg_time = sum(times) / len(times)
            avg_visited = sum(visiteds) / len(visiteds)
            avg_length = sum(lengths) / len(lengths)
            results.append({
                "maze": maze_name,
                "strategy": strat_name,
                "avg_time_ms": avg_time,
                "avg_visited": avg_visited,
                "avg_path_length": avg_length
            })
            print(f"{maze_name},{strat_name}: time={avg_time:.2f}ms visited={avg_visited:.0f} length={avg_length:.0f}")

    with open("experiment_results.csv", "w", newline='', encoding='utf-8') as f:
        writer = csv.DictWriter(f, fieldnames=["maze", "strategy", "avg_time_ms", "avg_visited", "avg_path_length"])
        writer.writeheader()
        writer.writerows(results)
    print("\nРезультаты сохранены в experiment_results.csv")

if __name__ == "__main__":
    demo()
    print("\n=== ЗАПУСК ЭКСПЕРИМЕНТОВ ===")
    run_experiments()