import glob
import json
import os
import matplotlib.pyplot as plt

# ---------- PARAMETERS ----------
RESULTS_DIR = "."                       # folder to scan for result json files
FILE_PATTERN = "*_shuffle_results.json" # only look at files matching this pattern
SUMMARY_OUTPUT_FILE = "shuffle_comparison_summary.json"
CHART_FILE_TEMPLATE = "{deck_name}_randomness_chart.png"  # one chart per deck
# ---------------------------------


def guess_method_name(filepath, settings):
    """Use the METHOD field if the file has one, otherwise derive a name from the filename."""
    if "METHOD" in settings:
        return settings["METHOD"]

    base = os.path.basename(filepath)
    base = base.replace("_shuffle_results.json", "")
    # strip a leading "<DeckName>_" if present
    deck_name = settings.get("DECK", "")
    if deck_name and base.startswith(deck_name):
        base = base[len(deck_name):].lstrip("_")
    return base if base else "Standard Riffle"


def load_all_results():
    files = glob.glob(os.path.join(RESULTS_DIR, FILE_PATTERN))
    grouped = {}  # deck_name -> list of {method, per-shuffle-count randomness}

    for filepath in files:
        with open(filepath) as f:
            data = json.load(f)

        settings = data.get("settings", {})
        results = data.get("results", {})
        deck_name = settings.get("DECK", "Unknown")
        method_name = guess_method_name(filepath, settings)

        per_shuffle = {}
        for num_shuffles, r in results.items():
            avg = r["avg_rising_sequences"]
            target = r["target_random_avg"]
            pct = (avg / target) * 100 if target else 0
            per_shuffle[int(num_shuffles)] = {
                "avg_rising_sequences": avg,
                "target_random_avg": target,
                "pct_of_random": round(pct, 1),
            }

        grouped.setdefault(deck_name, []).append({
            "method": method_name,
            "source_file": os.path.basename(filepath),
            "per_shuffle": per_shuffle,
        })

    return grouped


def print_report(grouped):
    for deck_name in sorted(grouped.keys()):
        print("=" * 70)
        print(f"DECK: {deck_name}")
        print("=" * 70)

        methods = grouped[deck_name]

        # collect the full set of shuffle-counts seen across methods for this deck
        all_counts = sorted({c for m in methods for c in m["per_shuffle"].keys()})

        header = "Method".ljust(22) + "".join(f"{c:>8}" for c in all_counts)
        print(header)
        print("-" * len(header))

        for m in methods:
            row = m["method"].ljust(22)
            for c in all_counts:
                cell = m["per_shuffle"].get(c)
                row += f"{cell['pct_of_random']:>7.1f}%" if cell else f"{'--':>8}"
            print(row)

        print("\n(values are % of a truly random deck's rising-sequence count; 100% = as random as shuffling gets)\n")

        # quick "best method at 7 shuffles" callout, if available
        best = None
        for m in methods:
            cell = m["per_shuffle"].get(7)
            if cell and (best is None or cell["pct_of_random"] > best[1]):
                best = (m["method"], cell["pct_of_random"])
        if best:
            print(f"Best at 7 shuffles: {best[0]} ({best[1]:.1f}% of random)\n")


def plot_deck(deck_name, methods):
    plt.figure(figsize=(9, 6))

    for m in methods:
        counts = sorted(m["per_shuffle"].keys())
        pct_values = [m["per_shuffle"][c]["pct_of_random"] for c in counts]
        plt.plot(counts, pct_values, marker="o", label=m["method"])

    plt.axhline(100, color="gray", linestyle="--", linewidth=1, label="Fully random (100%)")
    plt.title(f"Shuffle randomness vs. number of shuffles — {deck_name} deck")
    plt.xlabel("Number of shuffles")
    plt.ylabel("Randomness (% of a truly random deck)")
    plt.legend()
    plt.grid(True, alpha=0.3)

    output_path = CHART_FILE_TEMPLATE.format(deck_name=deck_name)
    plt.savefig(output_path, dpi=150, bbox_inches="tight")
    plt.close()
    print(f"Chart saved to {output_path}")


def save_summary(grouped):
    with open(SUMMARY_OUTPUT_FILE, "w") as f:
        json.dump(grouped, f, indent=2)
    print(f"Full summary written to {SUMMARY_OUTPUT_FILE}")


def main():
    grouped = load_all_results()
    if not grouped:
        print(f"No files matching '{FILE_PATTERN}' found in '{RESULTS_DIR}'.")
        return
    print_report(grouped)
    for deck_name, methods in grouped.items():
        plot_deck(deck_name, methods)
    save_summary(grouped)


if __name__ == "__main__":
    main()