import csv
from pathlib import Path
from typing import List, Dict, Any

from builders import TextFileMazeBuilder
from solver import MazeSolver
from strategies import BFSStrategy, DFSStrategy, AStarStrategy


class ExperimentRunner:
    
    def __init__(self):
        self.builder = TextFileMazeBuilder()
        self.strategies = [
            BFSStrategy(),
            DFSStrategy(),
            AStarStrategy()
        ]
    
    def run_experiment(self, maze_file: str, runs: int = 5) -> List[Dict[str, Any]]:
        
        try:
            maze = self.builder.build_from_file(maze_file)
        except ValueError as e:
            # Если лабиринт некорректный (нет старта или выхода)
            print(f"  Пропуск: {e}")
            return []
        
        results = []
        
        for strategy in self.strategies:
            solver = MazeSolver(maze, strategy)
            
            times = []
            path_lengths = []
            
            for _ in range(runs):
                try:
                    path, stats = solver.solve()
                    times.append(stats.time_ms)
                    path_lengths.append(stats.path_length)
                except Exception as e:
                    print(f"  Ошибка при {strategy.name}: {e}")
                    continue
            
            if times:
                results.append({
                    'maze': Path(maze_file).stem,
                    'strategy': strategy.name,
                    'avg_time_ms': sum(times) / runs,
                    'min_time_ms': min(times),
                    'max_time_ms': max(times),
                    'path_length': path_lengths[0] if path_lengths else 0,
                    'path_found': path_lengths[0] > 0 if path_lengths else False
                })
        
        return results
    
    def run_all_experiments(self, maze_files: List[str], runs: int = 5, 
                           output_file: str = "results/experiment_results.csv"):
        
        all_results = []
        
        for maze_file in maze_files:
            print(f"Запуск на лабиринте: {maze_file}")
            results = self.run_experiment(maze_file, runs)
            
            if results:
                all_results.extend(results)
                for r in results:
                    status = "✓" if r['path_found'] else "✗ (нет пути)"
                    print(f"  {r['strategy']}: {r['avg_time_ms']:.3f} мс, путь: {r['path_length']} {status}")
            else:
                print(f"  Лабиринт пропущен (нет старта или выхода)")
        
        if not all_results:
            print("Нет результатов для сохранения!")
            return
        
        # Сохранение в CSV
        Path("results").mkdir(exist_ok=True)
        with open(output_file, 'w', newline='', encoding='utf-8') as f:
            writer = csv.DictWriter(f, fieldnames=all_results[0].keys())
            writer.writeheader()
            writer.writerows(all_results)
        
        print(f"\nРезультаты сохранены в {output_file}")
        return all_results