import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import seaborn as sns
from scipy import stats
from scipy.stats import gaussian_kde

# Path Configuration
# MT5 terminal sandbox default path (Windows):
# C:\Users\<user>\AppData\Roaming\MetaQuotes\Terminal\<InstanceID>\MQL5\Files\
# Adjust DATA_PATH to point to your local MT5 Files directory.

BASE_DIR   = os.path.dirname(os.path.abspath(__file__))
DATA_PATH  = os.path.join(BASE_DIR, "exports", "analytics_export.csv")
OUTPUT_DIR = os.path.join(BASE_DIR, "charts")
os.makedirs(OUTPUT_DIR, exist_ok=True)

# Load the normalized analytics export
df = pd.read_csv(DATA_PATH)

# Global Style Configuration
plt.rcParams.update({
    "figure.facecolor"  : "#0d1117",
    "axes.facecolor"    : "#161b22",
    "axes.edgecolor"    : "#30363d",
    "axes.labelcolor"   : "#c9d1d9",
    "xtick.color"       : "#8b949e",
    "ytick.color"       : "#8b949e",
    "text.color"        : "#c9d1d9",
    "grid.color"        : "#21262d",
    "grid.linestyle"    : "--",
    "grid.linewidth"    : 0.6,
    "font.family"       : "monospace",
    "font.size"         : 9,
})


def plot_walkforward_degradation(df: pd.DataFrame,
                                  top_n: int = 20,
                                  save_path: str = None):
    """
    Walk-Forward Performance Degradation Profile (Paired Slope Chart)

    Draws a slope chart pairing IS_Score (In-Sample) with OOS_Score
    (Out-of-Sample) for the top_n configurations ranked by IS_Score.
    Line color encodes degradation magnitude: green = moderate,
    orange = significant, red = collapse.

    Parameters
    ----------
    df        : Full analytics DataFrame from CSV export.
    top_n     : Number of top in-sample configurations to display.
    save_path : File path for saving the output figure (optional).
    """

    required = ["IS_Score", "OOS_Score", "Symbol", "Filter_Period", "Indicator_Name"]
    plot_df  = df[required].dropna().copy()
    plot_df  = plot_df.nlargest(top_n, "IS_Score").reset_index(drop=True)

    plot_df["Degradation"] = plot_df["OOS_Score"] / (plot_df["IS_Score"].abs() + 1e-9)

    def assign_color(ratio):
        if ratio >= 0.70:
            return "#3fb950"    # Retained >= 70% of IS performance
        elif ratio >= 0.35:
            return "#d29922"    # Moderate degradation (35–70%)
        else:
            return "#f85149"    # Collapse below 35% of IS performance

    plot_df["LineColor"] = plot_df["Degradation"].apply(assign_color)

    fig, ax = plt.subplots(figsize=(8.167, 6.2))
    fig.suptitle(
        "Walk-Forward Performance Degradation Profile  |  IS vs OOS Structural Decay",
        fontsize=11, fontweight="bold", color="#e6edf3"
    )

    x_left  = 0.0
    x_right = 1.0
    y_min = min(plot_df["IS_Score"].min(), plot_df["OOS_Score"].min()) - 0.05
    y_max = max(plot_df["IS_Score"].max(), plot_df["OOS_Score"].max()) + 0.05

    for _, row in plot_df.iterrows():
        y_is  = row["IS_Score"]
        y_oos = row["OOS_Score"]
        color = row["LineColor"]
        label = f"{row['Symbol']} | {row['Indicator_Name']} | P={int(row['Filter_Period'])}"

        ax.plot([x_left, x_right], [y_is, y_oos],
                color=color, linewidth=1.4, alpha=0.80, zorder=2)
        ax.scatter([x_left],  [y_is],  color=color, s=32, zorder=3, alpha=0.9)
        ax.scatter([x_right], [y_oos], color=color, s=32, zorder=3,
                   alpha=0.9, marker="D")
        ax.text(x_left - 0.03, y_is, label,
                ha="right", va="center", fontsize=6.2, color="#8b949e")

    ax.axvline(x_left,  color="#484f58", linewidth=0.7, linestyle="--", zorder=1)
    ax.axvline(x_right, color="#484f58", linewidth=0.7, linestyle="--", zorder=1)
    ax.text(x_left,  y_max + 0.01, "In-Sample Score",
            ha="center", fontsize=9, fontweight="bold", color="#c9d1d9")
    ax.text(x_right, y_max + 0.01, "Out-of-Sample Score",
            ha="center", fontsize=9, fontweight="bold", color="#c9d1d9")

    from matplotlib.lines import Line2D
    legend_handles = [
        Line2D([0],[0], color="#3fb950", lw=2, label="Moderate Decay (>=70% retained)"),
        Line2D([0],[0], color="#d29922", lw=2, label="Significant Decay (35–70%)"),
        Line2D([0],[0], color="#f85149", lw=2, label="Collapse (<35% retained)"),
    ]
    ax.legend(handles=legend_handles, fontsize=8,
              loc="upper center", bbox_to_anchor=(0.5, -0.04),
              ncol=3, framealpha=0.2, edgecolor="#30363d")

    ax.set_xlim(-0.65, 1.55)
    ax.set_ylim(y_min, y_max + 0.12)
    ax.set_xticks([])
    ax.set_ylabel("Performance Score (Normalized)", fontsize=9, labelpad=8)
    ax.grid(axis="y", alpha=0.25)
    ax.spines[["top", "right", "bottom"]].set_visible(False)
    plt.tight_layout()

    if save_path:
        plt.savefig(save_path, dpi=120, bbox_inches="tight",
                    facecolor=fig.get_facecolor())
    plt.show()


# Execute
plot_walkforward_degradation(
    df, top_n=20,
    save_path=os.path.join(OUTPUT_DIR, "WalkForward_Degradation_Slope.png")
)