"""
Radar chart generator for Thesis Alignment.

Generates a 6-axis radar chart showing:
- Financial Health (incorporates D/E, ROA)
- Growth Transition
- Valuation Alignment
- Undiscovered Status
- Regulatory Risk (PFIC, VIE, CMIC, ADR)
- Jurisdiction Score (country/exchange stability)
"""

from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import structlog

from src.charts.base import ChartConfig, ChartFormat, RadarChartData

logger = structlog.get_logger(__name__)


def generate_radar_chart(
    data: RadarChartData,
    config: ChartConfig | None = None,
) -> Path | None:
    """Generate thesis alignment radar chart.

    Args:
        data: RadarChartData with normalized scores (0-100)
        config: ChartConfig for styling options

    Returns:
        Path to generated image file, or None if generation failed
    """
    config = config or ChartConfig()
    config.output_dir.mkdir(parents=True, exist_ok=True)

    # Set style
    sns.set_style("whitegrid")

    # 6 Dimensions - ordered for visual balance (alternating position importance)
    # Top: Health, Growth (most important)
    # Sides: Valuation, Regulatory
    # Bottom: Undiscovered, Jurisdiction
    categories = [
        "Health",
        "Growth",
        "Valuation",
        "Regulatory",
        "Undiscovered",
        "Jurisdiction",
    ]
    values = [
        data.health_score,
        data.growth_score,
        data.valuation_score,
        data.regulatory_score,
        data.undiscovered_score,
        data.jurisdiction_score,
    ]

    # Clamp values to 0-100 range (defensive)
    values = [max(0.0, min(100.0, v)) for v in values]

    # Close the loop for radar chart
    values_closed = values + values[:1]
    num_vars = len(categories)
    angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
    angles_closed = angles + angles[:1]

    # Create plot - slightly larger for 6 axes
    fig, ax = plt.subplots(
        figsize=(config.width_inches, config.height_inches),
        subplot_kw=({"polar": True}),
    )

    # Handle transparency
    if config.transparent:
        fig.patch.set_alpha(0)
        ax.patch.set_alpha(0)
        ax.set_facecolor((0, 0, 0, 0))
    else:
        fig.patch.set_facecolor("white")
        ax.patch.set_facecolor("white")

    # Set colors based on transparency to ensure visibility on both dark/light themes
    if config.transparent:
        # Mid-tone colors that avoid extremes
        axis_label_color = "#4A90D9"  # Mid Blue
        data_label_color = "#00B4D8"  # Mid Cyan
        tick_label_color = "#7F7F7F"  # Mid Grey
        title_color = "#4A90D9"  # Mid Blue
    else:
        axis_label_color = "grey"
        data_label_color = "#0077B6"  # Darker Blue
        tick_label_color = "grey"
        title_color = "black"

    # Draw axis labels (categories) with abbreviations for long names
    # Use shorter labels to prevent overlap with 6 axes
    display_labels = [
        "Financial Health",
        "Growth",
        "Valuation",
        "Regulatory",
        "Undiscovered",
        "Jurisdiction",
    ]

    # Apply warning markers
    AXIS_KEYS = [
        "health",
        "growth",
        "valuation",
        "regulatory",
        "undiscovered",
        "jurisdiction",
    ]
    if data.axis_warnings:
        display_labels = [
            label + ("*" if data.axis_warnings.get(key) else "")
            for label, key in zip(display_labels, AXIS_KEYS, strict=True)
        ]

    # Use OO API for thread-safety (avoid plt global state)
    ax.set_xticks(angles)
    ax.set_xticklabels(display_labels, color=axis_label_color, size=8)

    # Push the axis labels (categories) further out to avoid overlapping with data labels
    # Reduced pad from 30 to 25 for 6-axis (labels are shorter, so less pad needed)
    ax.tick_params(axis="x", pad=32)

    # Draw ylabels - positioned at 30 degrees to avoid overlap with top axis
    ax.set_rlabel_position(30)
    ax.set_yticks([25, 50, 75])
    ax.set_yticklabels(["25", "50", "75"], color=tick_label_color, size=7)
    ax.set_ylim(0, 100)

    # Plot data - Using colorblind-safe Cyan (matches PASS color in CLI)
    chart_color = "#00B4D8"  # Cyan/Blue

    ax.plot(
        angles_closed, values_closed, linewidth=2, linestyle="solid", color=chart_color
    )

    # Fill area
    ax.fill(angles_closed, values_closed, chart_color, alpha=0.25)

    # Add data value labels
    # Position labels carefully to avoid overlap with axis labels
    for angle, value, _label in zip(angles, values, categories, strict=True):
        # Calculate label offset based on value
        # Low values: push label outward so it's visible
        # High values: keep label close but above the line
        if value < 30:
            label_r = value + 18  # Push out more for low values
        elif value > 80:
            label_r = value + 12  # Less offset for high values (near edge)
        else:
            label_r = value + 15  # Standard offset

        # Ensure label doesn't exceed chart bounds
        label_r = min(label_r, 98)

        ax.text(
            angle,
            label_r,
            f"{value:.0f}%",
            ha="center",
            va="center",
            fontsize=8,
            fontweight="bold",
            color=data_label_color,
        )

    # Render Footnote
    if data.footnote:
        fig.text(
            0.5,
            0.02,
            data.footnote,
            ha="center",
            fontsize=7,
            color=tick_label_color,
            style="italic",
        )

    # Title - use fig.suptitle (OO API) to keep it fixed at top, avoiding axis label overlap
    title_text = f"{data.ticker} Thesis Alignment ({data.trade_date})"

    fig.suptitle(title_text, size=10, y=0.98, fontweight="bold", color=title_color)

    # Reserve top space for title (0.92 top limit) and bottom for footnotes
    fig.tight_layout(rect=[0, 0.08, 1, 0.92])

    # Generate filename - use config.filename_stem if provided, else ticker_date
    if config.filename_stem:
        filename = f"{config.filename_stem}_radar"
    else:
        safe_ticker = data.ticker.replace(".", "_").replace("/", "_")
        filename = f"{safe_ticker}_{data.trade_date}_radar"

    # Save (use fig.savefig for OO API)
    if config.format == ChartFormat.SVG:
        output_path = config.output_dir / f"{filename}.svg"
        fig.savefig(
            output_path,
            format="svg",
            dpi=config.dpi,
            transparent=config.transparent,
            bbox_inches="tight",
        )
    else:
        output_path = config.output_dir / f"{filename}.png"
        fig.savefig(
            output_path,
            format="png",
            dpi=config.dpi,
            transparent=config.transparent,
            bbox_inches="tight",
        )

    plt.close(fig)

    logger.info(
        "Generated radar chart",
        ticker=data.ticker,
        output_path=str(output_path),
    )

    return output_path
