"""plot_results.py - графики для эксперимента с лабиринтами."""
import csv
import os
import matplotlib.pyplot as plt
import numpy as np

CSV = "docs/data/results.csv"
PLOTS = "docs/data/plots"
os.makedirs(PLOTS, exist_ok=True)


def load_means():
    """Возвращает dict[(maze, strategy)] = (time_ms, visited, path_len, cost)."""
    out = {}
    with open(CSV, encoding="utf-8") as f:
        rows = list(csv.reader(f))
    start = next(i for i, r in enumerate(rows) if r and r[0] == "--- СРЕДНИЕ ---") + 2
    for r in rows[start:]:
        if not r:
            continue
        maze, strat, t, vis, plen, cost = r
        out[(maze, strat)] = (float(t), int(vis), int(plen), int(cost))
    return out


MAZES = ["small_10x10", "medium_51x51", "large_101x101",
         "empty_30x30", "nopath_15x15",
         "weighted_31x31", "weighted_choice"]
STRATEGIES = ["BFS", "DFS", "A*", "Dijkstra"]
COLORS = {"BFS": "#3498db", "DFS": "#e67e22", "A*": "#2ecc71", "Dijkstra": "#9b59b6"}


def grouped_bar(means, idx, ylabel, title, fname, log=True):
    x = np.arange(len(MAZES))
    w = 0.2
    fig, ax = plt.subplots(figsize=(11, 5))
    for i, s in enumerate(STRATEGIES):
        vals = [means[(m, s)][idx] for m in MAZES]
        bars = ax.bar(x + (i - 1.5) * w, vals, w, label=s, color=COLORS[s], alpha=0.9)
        for b, v in zip(bars, vals):
            ax.text(b.get_x() + b.get_width() / 2, b.get_height(),
                    f"{v:g}", ha="center", va="bottom", fontsize=7, rotation=0)
    ax.set_xticks(x)
    ax.set_xticklabels(MAZES, rotation=20, ha="right")
    ax.set_ylabel(ylabel)
    ax.set_title(title)
    if log:
        ax.set_yscale("log")
    ax.legend()
    ax.grid(axis="y", linestyle="--", alpha=0.4)
    plt.tight_layout()
    p = os.path.join(PLOTS, fname)
    plt.savefig(p, dpi=130)
    plt.close()
    print("saved:", p)


def weighted_choice_chart(means):
    """Отдельный график для weighted_choice: путь vs стоимость."""
    strategies = STRATEGIES
    lengths = [means[("weighted_choice", s)][2] for s in strategies]
    costs   = [means[("weighted_choice", s)][3] for s in strategies]
    x = np.arange(len(strategies))
    w = 0.35
    fig, ax = plt.subplots(figsize=(7.5, 4.5))
    b1 = ax.bar(x - w/2, lengths, w, label="длина пути (клеток)",
                color="#3498db", alpha=0.9)
    b2 = ax.bar(x + w/2, costs, w, label="стоимость пути (сумма весов)",
                color="#e74c3c", alpha=0.9)
    for bars in (b1, b2):
        for bar in bars:
            ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height(),
                    f"{bar.get_height():.0f}", ha="center", va="bottom", fontsize=9)
    ax.set_xticks(x); ax.set_xticklabels(strategies)
    ax.set_title("weighted_choice: BFS/DFS режут через болото,\n"
                 "Dijkstra/A* находят более дешёвый обход")
    ax.set_ylabel("значение")
    ax.legend()
    ax.grid(axis="y", linestyle="--", alpha=0.4)
    plt.tight_layout()
    p = os.path.join(PLOTS, "weighted_choice_compare.png")
    plt.savefig(p, dpi=130)
    plt.close()
    print("saved:", p)


def main():
    means = load_means()
    grouped_bar(means, 0, "Время, мс (среднее по 7 запускам, лог. шкала)",
                "Время поиска пути", "time_compare.png", log=True)
    grouped_bar(means, 1, "Число посещённых клеток (лог. шкала)",
                "Сколько клеток посетил алгоритм", "visited_compare.png", log=True)
    grouped_bar(means, 2, "Длина пути (клеток)",
                "Длина найденного пути", "path_compare.png", log=False)
    weighted_choice_chart(means)


if __name__ == "__main__":
    main()
