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_multi_asset_parameter_matrix(df: pd.DataFrame,
                                      target_period: int = 30,
                                      save_path: str = None):
    """
    Multi-Asset Parameter Match Matrix (Diverging Bar Chart)

    Filters the analytics export to a single Filter_Period and constructs
    a diverging horizontal bar plot comparing normalized performance metrics
    across all unique Symbol values present in that subset.

    Parameters
    ----------
    df            : Full analytics DataFrame from CSV export.
    target_period : The Filter_Period integer to isolate for comparison.
    save_path     : File path for saving the output figure (optional).
    """

    # --- Data Preparation
    subset = df[df["Filter_Period"] == target_period].copy()

    if subset.empty:
        raise ValueError(f"No records found for Filter_Period = {target_period}.")

    # Metrics to include in the comparison matrix
    metric_cols = ["Net_Profit_USD", "Sortino_Ratio", "Max_Drawdown_PCT",
                   "False_Flips_Whipsaws", "Trade_Count"]

    # Invert Max_Drawdown and False_Flips so higher = better across all fields
    subset["Max_Drawdown_PCT"]     = -subset["Max_Drawdown_PCT"]
    subset["False_Flips_Whipsaws"] = -subset["False_Flips_Whipsaws"]

    # Z-score normalization per metric column so all axes share a common scale
    for col in metric_cols:
        col_mean = subset[col].mean()
        col_std  = subset[col].std()
        subset[col + "_z"] = (subset[col] - col_mean) / (col_std + 1e-9)

    z_cols    = [c + "_z" for c in metric_cols]
    symbols   = subset["Symbol"].unique()
    n_metrics = len(metric_cols)

    # Aggregate to symbol-level mean z-scores where multiple timeframes exist
    agg = subset.groupby("Symbol")[z_cols].mean().reset_index()

    # --- Figure Layout
    fig, axes = plt.subplots(1, n_metrics,
                             figsize=(8.167, max(3.5, len(symbols) * 0.55 + 1.5)),
                             sharey=True)
    fig.suptitle(
        f"Multi-Asset Parameter Match Matrix  |  Filter Period: {target_period}",
        fontsize=11, fontweight="bold", color="#e6edf3", y=1.01
    )

    display_labels = {
        "Net_Profit_USD_z"       : "Net Profit (Normalized)",
        "Sortino_Ratio_z"        : "Sortino Ratio",
        "Max_Drawdown_PCT_z"     : "Max DD (Inverted)",
        "False_Flips_Whipsaws_z" : "Whipsaws (Inverted)",
        "Trade_Count_z"          : "Trade Count",
    }

    bar_colors_pos = "#3fb950"   # Green for positive z-score
    bar_colors_neg = "#f85149"   # Red for negative z-score

    for ax_idx, (ax, z_col) in enumerate(zip(axes, z_cols)):
        values     = agg[z_col].values
        sym_labels = agg["Symbol"].values
        y_pos      = np.arange(len(sym_labels))

        colors = [bar_colors_pos if v >= 0 else bar_colors_neg for v in values]
        bars   = ax.barh(y_pos, values, color=colors, height=0.62, alpha=0.88)

        ax.axvline(0, color="#484f58", linewidth=0.9, linestyle="-")
        ax.set_title(display_labels.get(z_col, z_col),
                     fontsize=8, color="#8b949e", pad=6)
        ax.tick_params(axis="x", labelsize=7)
        ax.grid(axis="x", alpha=0.4)
        ax.set_xlim(-3.5, 3.5)
        ax.spines[["top", "right"]].set_visible(False)

        # Annotate each bar with its raw z-score
        for bar_rect, val in zip(bars, values):
            label_x = bar_rect.get_width() + (0.08 if val >= 0 else -0.08)
            ha       = "left" if val >= 0 else "right"
            ax.text(label_x, bar_rect.get_y() + bar_rect.get_height() / 2,
                    f"{val:+.2f}", va="center", ha=ha, fontsize=6.5,
                    color="#8b949e")

        if ax_idx == 0:
            ax.set_yticks(y_pos)
            ax.set_yticklabels(sym_labels, fontsize=8)

    fig.text(0.5, -0.03,
             "Z-score deviation from group mean  |  Higher = Structurally Stronger",
             ha="center", fontsize=7.5, color="#8b949e", style="italic")

    plt.tight_layout()

    if save_path:
        plt.savefig(save_path, dpi=120, bbox_inches="tight",
                    facecolor=fig.get_facecolor())
    plt.show()


# Execute
plot_multi_asset_parameter_matrix(
    df,
    target_period=30,
    save_path=os.path.join(OUTPUT_DIR, "Multi_Asset_Parameter_Matrix.png")
)
