"""
NGR Analysis and Visualization Module

This module provides functions for analyzing and visualizing NGR (Net Gaming Revenue)
predictions and actual values, including segmentation and error metrics calculation.
"""

from typing import Dict, Optional

import matplotlib.pyplot as plt
import pandas as pd

from .metrics import calculate_ngr_metrics


def print_ngrs_improved(
    df: pd.DataFrame,
    additional_text: str = "",
    late_stage_day: Optional[int] = None,
    late_stage_correction: Optional[float] = None,
) -> Dict[str, float]:
    """
    Calculate and visualize NGR metrics grouped by days_since_ftd with business-optimal weighting.

    This function aggregates predictions and actual values, applies optional late-stage corrections,
    calculates various error metrics (MAE, MAPE, ME, MPE) with business weights, and generates
    a comprehensive visualization.

    Parameters
    ----------
    df : pd.DataFrame
        DataFrame containing prediction results with columns:
        - 'days_since_ftd': int, days since first time deposit
        - 'remaining_ngr': float, actual remaining NGR
        - 'remaining_ngr_pred': float, predicted remaining NGR
    additional_text : str, default=''
        Additional text to append to plot title
    late_stage_day : int, optional
        Day threshold after which to apply correction
    late_stage_correction : float, optional
        Correction factor to apply (0.0-1.0) linearly after late_stage_day

    Returns
    -------
    Dict[str, float]
        Dictionary containing calculated metrics:
        - 'Standard MAE': Mean Absolute Error
        - 'Standard MAPE (%)': Mean Absolute Percentage Error
        - 'Business Optimal MAE': Weighted MAE
        - 'Business Optimal MAPE (%)': Weighted MAPE

    Notes
    -----
    Business-optimal weights by day ranges:
    - Days 1-7: 0.05 (learning period - insufficient data)
    - Days 8-14: 0.85 (early signals emerging)
    - Days 15-45: 1.00 (🥇 SUPER CRITICAL - optimal intervention window)
    - Days 46-90: 0.90 (confirmation period - high value)
    - Days 91-180: 0.60 (established patterns - moderate value)
    - Days 181-270: 0.40 (mature behavior - operational value)
    - Days 271+: 0.30 (end-game precision - tactical value)

    Examples
    --------
    >>> metrics = print_ngrs_improved(
    ...     df,
    ...     additional_text='(Q4 2024)',
    ...     late_stage_day=320,
    ...     late_stage_correction=0.95
    ... )
    >>> print(f"Business MAE: {metrics['Business Optimal MAE']:.2f}")
    """
    # Calculate all metrics using the separate calculation function
    metrics = calculate_ngr_metrics(df, late_stage_day, late_stage_correction)

    # Extract calculated values
    mean_values = metrics["mean_values"]
    mean_abs_error_by_bin = metrics["mean_abs_error_by_bin"]

    standard_mae = metrics["Standard MAE"]
    standard_mape = metrics["Standard MAPE (%)"]
    business_optimal_tmae = metrics["Business Optimal MAE"]
    business_optimal_mape = metrics["Business Optimal MAPE (%)"]
    business_optimal_me = metrics["Business Optimal ME"]
    business_optimal_mpe = metrics["Business Optimal MPE (%)"]

    # Create visualization
    plt.figure(figsize=(14, 8))

    # Plot both lines on same axes
    plt.plot(mean_values["days_since_ftd"], mean_values["remaining_ngr"], "b-", label="Actual NGR", linewidth=2)
    plt.plot(mean_values["days_since_ftd"], mean_values["remaining_ngr_pred"], "r-", label="Predicted NGR", linewidth=2)

    # Add business-optimal period reference lines
    plt.axvline(x=7, color="red", linestyle="--", alpha=0.8, linewidth=1)
    plt.axvline(x=14, color="orange", linestyle="--", alpha=0.8, linewidth=1)
    plt.axvline(x=45, color="gold", linestyle="--", alpha=0.9, linewidth=1)
    plt.axvline(x=90, color="green", linestyle="--", alpha=0.8, linewidth=1)
    plt.axvline(x=180, color="blue", linestyle="--", alpha=0.7, linewidth=1)
    plt.axvline(x=270, color="purple", linestyle="--", alpha=0.6, linewidth=1)

    # Add weight labels at the top of each period
    y_max = max(mean_values["remaining_ngr"].max(), mean_values["remaining_ngr_pred"].max())
    y_text = y_max * 0.85  # Position text at 85% of max height

    plt.text(3.5, y_text, "0.05", ha="center", va="center", fontsize=10, fontweight="bold")
    plt.text(10.5, y_text, "0.85", ha="center", va="center", fontsize=10, fontweight="bold")
    plt.text(29.5, y_text, "1.00", ha="center", va="center", fontsize=10, fontweight="bold")
    plt.text(67.5, y_text, "0.90", ha="center", va="center", fontsize=10, fontweight="bold")
    plt.text(135, y_text, "0.60", ha="center", va="center", fontsize=10, fontweight="bold")
    plt.text(225, y_text, "0.40", ha="center", va="center", fontsize=10, fontweight="bold")

    # For the last period, calculate center dynamically
    max_days = mean_values["days_since_ftd"].max()
    if max_days > 270:
        last_center = (270 + max_days) / 2
        plt.text(last_center, y_text, "0.30", ha="center", va="center", fontsize=10, fontweight="bold")

    plt.xlabel("Days Since First Time Deposit", fontsize=12)
    plt.ylabel("Average Remaining NGR", fontsize=12)
    title = f"Actual vs Predicted Average Remaining NGR by Days Since FTD {additional_text}"
    plt.title(title, fontsize=14)
    plt.grid(True, alpha=0.3)
    plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")

    # Create metrics text with MAE and MAPE
    metrics_text = "Model Performance Metrics:\n"
    metrics_text += f"Business Optimal MAE: {business_optimal_tmae:.2f}\n"
    metrics_text += f"Business Optimal ME: {business_optimal_me:.2f}\n"
    metrics_text += f"Business Optimal MAPE: {business_optimal_mape:.1f}%\n"
    metrics_text += f"Business Optimal MPE: {business_optimal_mpe:.1f}%\n\n"

    # Add mean_abs_error_by_bin to the metrics text
    metrics_text += "Mean Abs Error by Period:\n"
    for _, row in mean_abs_error_by_bin.iterrows():
        metrics_text += f"{row['bin']}: {row['mean_abs_error']:.2f}\n"

    metrics_text += "\nMean ABS PERCENT Error by Period:\n"
    for _, row in mean_abs_error_by_bin.iterrows():
        metrics_text += f"{row['bin']}: {row['mape']:.2f}%\n"

    # Add metrics in top right corner
    plt.text(
        0.98,
        0.98,
        metrics_text,
        transform=plt.gca().transAxes,
        verticalalignment="top",
        horizontalalignment="right",
        bbox={"boxstyle": "round", "facecolor": "lightblue", "alpha": 0.9},
        fontsize=9,
        fontweight="bold",
        fontfamily="monospace",
    )

    plt.tight_layout()
    plt.show()
    plt.close()

    # Return dict with MAE and MAPE metrics
    return {
        "Standard MAE": standard_mae,
        "Standard MAPE (%)": round(standard_mape, 1),
        "Business Optimal MAE": round(business_optimal_tmae, 2),
        "Business Optimal MAPE (%)": round(business_optimal_mape, 1),
    }
