#!/usr/bin/env python
# coding: utf-8

# In[ ]:


import csv
import time
from typing import List, Dict, Any
from modelsMaze import Maze
from strategiesBfs_strategy import BFSStrategy
from strategiesDfs_strategy import DFSStrategy
from strategiesA_star_strategy import AStarStrategy
from solverMaze_solver import MazeSolver

class Benchmark:
    """Экспериментальное сравнение алгоритмов."""

    def __init__(self):
        self.strategies = [
            BFSStrategy(),
            DFSStrategy(),
            AStarStrategy(),
        ]
        self.results: List[Dict[str, Any]] = []

    def run_on_maze(self, maze: Maze, maze_name: str, iterations: int = 5) -> List[Dict]:
        """Запустить все стратегии на одном лабиринте."""
        results = []

        for strategy in self.strategies:
            solver = MazeSolver(maze, strategy)

            times = []
            visited_counts = []
            path_lengths = []
            path_found = False

            for i in range(iterations):
                # Сбрасываем состояние стратегии для честного замера
                # (кэш посещённых клеток не должен влиять)
                start_time = time.perf_counter()
                path = strategy.find_path(maze, maze.start_cell, maze.exit_cell)
                end_time = time.perf_counter()

                times.append((end_time - start_time) * 1000)
                visited_counts.append(getattr(strategy, 'last_visited_count', 0))
                path_lengths.append(len(path))
                path_found = len(path) > 0

            result = {
                'maze': maze_name,
                'algorithm': strategy.name,
                'avg_time_ms': sum(times) / len(times),
                'min_time_ms': min(times),
                'max_time_ms': max(times),
                'avg_visited': sum(visited_counts) / len(visited_counts),
                'avg_path_length': sum(path_lengths) / len(path_lengths),
                'path_found': path_found,
                'iterations': iterations
            }
            results.append(result)
            self.results.append(result)

        return results

    def save_to_csv(self, filename: str = "benchmark_results.csv") -> None:
        """Сохранить результаты в CSV."""
        if not self.results:
            print("Нет результатов для сохранения")
            return

        fieldnames = ['maze', 'algorithm', 'avg_time_ms', 'min_time_ms', 
                      'max_time_ms', 'avg_visited', 'avg_path_length', 
                      'path_found', 'iterations']

        with open(filename, 'w', newline='', encoding='utf-8') as f:
            writer = csv.DictWriter(f, fieldnames=fieldnames)
            writer.writeheader()
            writer.writerows(self.results)

        print(f"Результаты сохранены в {filename}")

    def print_summary(self) -> None:
        """Вывести сводку результатов."""
        print("РЕЗУЛЬТАТЫ ЭКСПЕРИМЕНТОВ")

        current_maze = None
        for r in self.results:
            if r['maze'] != current_maze:
                current_maze = r['maze']
                print(f"\n--- Лабиринт: {current_maze} ---")

            status = " НАЙДЕН" if r['path_found'] else " НЕ НАЙДЕН"
            print(f"  {r['algorithm']:6} | Время: {r['avg_time_ms']:8.2f} мс | "
                  f"Посещено: {r['avg_visited']:8.1f} | "
                  f"Путь: {r['avg_path_length']:6.1f} | {status}")



