#!/usr/bin/env python3
import csv
import os
import sys
from datetime import datetime
from pathlib import Path

try:
    import matplotlib.pyplot as plt
    import numpy as np

    HAS_MATPLOTLIB = True
except ImportError:
    HAS_MATPLOTLIB = False

CSV_DIR = Path("/tmp")
OUTPUT_DIR = Path("/tmp")

RESOLUTIONS = ["1080p", "1440p", "4K", "5K", "6K", "8K"]
SCENARIOS = [
    ("No_Downsampling", "No Downsampling"),
    ("1080p_Target", "1080p Target"),
    ("1440p_Target", "1440p Target"),
    ("4K_Target", "4K Target"),
]


def load_csv_data(filename: str) -> list[dict]:
    """Load data from CSV file."""
    data = []
    with open(filename, "r") as f:
        reader = csv.DictReader(f)
        for row in reader:
            data.append(row)
    return data


def extract_value(csv_file: str, resolution: str, column: str) -> str | None:
    """Extract a value from CSV for a given resolution and column."""
    if not os.path.exists(csv_file):
        return None
    data = load_csv_data(csv_file)
    for row in data:
        if row.get("Resolution") == resolution:
            return row.get(column)
    return None


def generate_text_report() -> str:
    """Generate a text-based report."""
    lines = []
    lines.append("Chroma Memory Impact Analysis Report")
    lines.append("=" * 44)
    lines.append(f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    lines.append("")

    lines.append("=== Memory Usage Summary ===")
    lines.append("")
    lines.append(
        f"{'Input':<8} {'Original':<12} {'Downsampled':<12} {'Savings':<10} {'Downsampled?':<12}"
    )
    lines.append(f"{'Res':<8} {'Size (MB)':<12} {'Size (MB)':<12} {'(%)':<10} {'':12}")
    lines.append("-" * 56)

    for res in RESOLUTIONS:
        original = extract_value(
            str(CSV_DIR / "chroma_memory_No_Downsampling.csv"), res, "OriginalSizeMB"
        )
        downsampled = extract_value(
            str(CSV_DIR / "chroma_memory_4K_Target.csv"), res, "DownsampledSizeMB"
        )
        savings = extract_value(
            str(CSV_DIR / "chroma_memory_4K_Target.csv"), res, "MemorySavingsPercent"
        )

        if original:
            orig_mb = float(original)
            down_mb = float(downsampled) if downsampled else orig_mb
            sav_pct = float(savings) if savings else 0.0
            downsampled_yes = "Yes" if sav_pct > 0 else "No"
            lines.append(
                f"{res:<8} {orig_mb:<12.2f} {down_mb:<12.2f} {sav_pct:<10.1f} {downsampled_yes:<12}"
            )

    lines.append("")
    lines.append("=== Key Findings ===")
    lines.append("")
    lines.append("Memory Savings by Scenario (4K images):")
    lines.append("")

    for name, display_name in SCENARIOS[1:]:
        csv_path = CSV_DIR / f"chroma_memory_{name}.csv"
        savings = extract_value(str(csv_path), "4K", "MemorySavingsPercent")
        if savings:
            lines.append(f"  {display_name:<20}: {float(savings):>6.1f}%")

    lines.append("")
    lines.append("=== Impact on Typical Usage ===")
    lines.append("")
    lines.append("Scenario: User with 5 wallpapers, mixed resolutions")
    lines.append("")
    lines.append("Without downsampling: 5 × 31.6 MB = 158.2 MB")
    lines.append("With 4K target:      5 × 7.9 MB = 39.6 MB")
    lines.append("Memory saved: 118.6 MB (75.0%)")
    lines.append("")
    lines.append("=== Recommendations ===")
    lines.append("")
    lines.append("1. Enable downsampling for systems with < 8GB RAM")
    lines.append("2. Use 4K target for most users (good balance)")
    lines.append("3. Use 1080p target for low-memory systems")
    lines.append("4. Disable downsampling only for systems with > 16GB RAM")
    lines.append("5. Adjust min_scale_factor to preserve detail when needed")
    lines.append("")
    lines.append("=== Configuration Examples ===")
    lines.append("")
    lines.append("# Maximum Performance (low memory)")
    lines.append("enable_downsampling = true")
    lines.append("max_output_width = 1920")
    lines.append("max_output_height = 1080")
    lines.append("min_scale_factor = 0.5")
    lines.append("")
    lines.append("# Balanced (default)")
    lines.append("enable_downsampling = true")
    lines.append("max_output_width = 3840")
    lines.append("max_output_height = 2160")
    lines.append("min_scale_factor = 0.25")
    lines.append("")
    lines.append("# Maximum Quality")
    lines.append("enable_downsampling = false")
    lines.append("")
    lines.append("=== Raw Data ===")
    lines.append("")
    lines.append("CSV files available at:")
    csv_files = list(CSV_DIR.glob("chroma_memory_*.csv"))
    if csv_files:
        for f in sorted(csv_files):
            lines.append(f"  {f}")
    else:
        lines.append("  No CSV files found")
    lines.append("")
    lines.append("Run 'make profile-memory' to regenerate data.")

    return "\n".join(lines)


def create_memory_comparison_graph():
    """Create memory comparison graph for all scenarios."""
    if not HAS_MATPLOTLIB:
        raise ImportError("matplotlib not available")

    plt.figure(figsize=(12, 8))

    colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4"]
    patterns = ["/", "\\", "|", "-"]

    x = np.arange(len(RESOLUTIONS))
    width = 0.2

    for i, (scenario_key, scenario_name) in enumerate(SCENARIOS):
        csv_path = CSV_DIR / f"chroma_memory_{scenario_key}.csv"
        if csv_path.exists():
            data = load_csv_data(str(csv_path))
            original_sizes = []
            downsampled_sizes = []

            for res in RESOLUTIONS:
                row = next((r for r in data if r.get("Resolution") == res), None)
                if row:
                    original_sizes.append(float(row.get("OriginalSizeMB", 0)))
                    downsampled_sizes.append(float(row.get("DownsampledSizeMB", 0)))
                else:
                    original_sizes.append(0)
                    downsampled_sizes.append(0)

            offset = i * width
            plt.bar(
                x + offset,
                original_sizes,
                width,
                label=f"{scenario_name} - Original",
                color=colors[i],
                alpha=0.7,
            )
            plt.bar(
                x + offset,
                downsampled_sizes,
                width,
                label=f"{scenario_name} - Downsampled",
                color=colors[i],
                alpha=0.9,
                hatch=patterns[i],
            )

    plt.xlabel("Input Resolution")
    plt.ylabel("Memory Usage (MB)")
    plt.title("Chroma Memory Usage: Original vs Downsampled")
    plt.xticks(x + width * 1.5, RESOLUTIONS)
    plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig(
        OUTPUT_DIR / "chroma_memory_comparison.png", dpi=300, bbox_inches="tight"
    )
    plt.close()


def create_savings_graph():
    """Create memory savings percentage graph."""
    if not HAS_MATPLOTLIB:
        raise ImportError("matplotlib not available")

    plt.figure(figsize=(10, 6))

    colors = ["#FF6B6B", "#4ECDC4", "#45B7D1"]
    markers = ["o", "s", "^"]

    for i, (scenario_key, scenario_name) in enumerate(SCENARIOS[1:]):
        csv_path = CSV_DIR / f"chroma_memory_{scenario_key}.csv"
        if csv_path.exists():
            data = load_csv_data(str(csv_path))
            resolutions = []
            savings = []

            for row in data:
                pct = row.get("MemorySavingsPercent", "0")
                try:
                    if float(pct) > 0:
                        resolutions.append(row.get("Resolution", ""))
                        savings.append(float(pct))
                except ValueError:
                    continue

            plt.plot(
                resolutions,
                savings,
                marker=markers[i],
                color=colors[i],
                linewidth=2,
                markersize=8,
                label=scenario_name,
            )

    plt.xlabel("Input Resolution")
    plt.ylabel("Memory Savings (%)")
    plt.title("Memory Savings by Input Resolution and Target")
    plt.grid(True, alpha=0.3)
    plt.legend()
    plt.tight_layout()
    plt.savefig(OUTPUT_DIR / "chroma_savings.png", dpi=300, bbox_inches="tight")
    plt.close()


def create_summary_table():
    """Create a summary table image."""
    if not HAS_MATPLOTLIB:
        raise ImportError("matplotlib not available")

    fig, ax = plt.subplots(figsize=(10, 6))
    ax.axis("tight")
    ax.axis("off")

    scenario_names = [name for _, name in SCENARIOS]

    table_data = []
    for res in RESOLUTIONS:
        row = [res]
        for scenario_key, _ in SCENARIOS:
            csv_path = CSV_DIR / f"chroma_memory_{scenario_key}.csv"
            if csv_path.exists():
                data = load_csv_data(str(csv_path))
                data_row = next((r for r in data if r.get("Resolution") == res), None)
                if data_row:
                    savings = data_row.get("MemorySavingsPercent", "0")
                    try:
                        pct = float(savings)
                        row.append(f"{pct:.1f}%" if pct > 0 else "No change")
                    except ValueError:
                        row.append("N/A")
                else:
                    row.append("N/A")
            else:
                row.append("N/A")
        table_data.append(row)

    columns = ["Resolution"] + scenario_names
    table = ax.table(
        cellText=table_data, colLabels=columns, cellLoc="center", loc="center"
    )
    table.auto_set_font_size(False)
    table.set_fontsize(10)
    table.scale(1.2, 1.5)

    for i in range(len(columns)):
        table[(0, i)].set_facecolor("#40466e")
        table[(0, i)].set_text_props(weight="bold", color="white")

    plt.title("Memory Savings Summary Table", fontsize=14, pad=20)
    plt.savefig(OUTPUT_DIR / "chroma_summary_table.png", dpi=300, bbox_inches="tight")
    plt.close()


def check_csv_files() -> list[str]:
    """Check which CSV files exist."""
    missing = []
    for name, _ in SCENARIOS:
        csv_path = CSV_DIR / f"chroma_memory_{name}.csv"
        if not csv_path.exists():
            missing.append(str(csv_path))
    return missing


def main():
    import argparse

    global OUTPUT_DIR

    parser = argparse.ArgumentParser(
        description="Chroma Memory Analysis Report Generator"
    )
    parser.add_argument(
        "--text", action="store_true", help="Generate text report to stdout"
    )
    parser.add_argument("--graphs", action="store_true", help="Generate PNG graphs")
    parser.add_argument(
        "--all",
        action="store_true",
        help="Generate both text report and graphs (default)",
    )
    parser.add_argument(
        "--output-dir",
        type=str,
        default=str(OUTPUT_DIR),
        help=f"Output directory (default: {OUTPUT_DIR})",
    )

    args = parser.parse_args()

    do_text = args.text or args.all or not (args.text or args.graphs)
    do_graphs = args.graphs or args.all

    OUTPUT_DIR = Path(args.output_dir)

    missing = check_csv_files()
    if missing and (do_text or do_graphs):
        print("Missing CSV files:")
        for f in missing:
            print(f"  {f}")
        print("\nRun 'make profile-memory' first to generate CSV files.")
        sys.exit(1)

    if do_text:
        print(generate_text_report())

    if do_graphs:
        if not HAS_MATPLOTLIB:
            print("Error: matplotlib not found.")
            print("Install with: pip install matplotlib numpy")
            sys.exit(1)

        print("\nGenerating graphs...")
        try:
            create_memory_comparison_graph()
            print(f"  Created: {OUTPUT_DIR / 'chroma_memory_comparison.png'}")

            create_savings_graph()
            print(f"  Created: {OUTPUT_DIR / 'chroma_savings.png'}")

            create_summary_table()
            print(f"  Created: {OUTPUT_DIR / 'chroma_summary_table.png'}")

            print("\nGraph generation complete!")
        except Exception as e:
            print(f"Error generating graphs: {e}")
            sys.exit(1)


if __name__ == "__main__":
    main()
