"""
Q2 2026 Board Presentation — Churn Analysis Charts
Generates exec-ready visualizations for the April 15 board meeting.
"""

import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import pandas as pd
import numpy as np

# -- Style setup --
plt.rcParams.update({
    "figure.facecolor": "white",
    "axes.facecolor": "white",
    "font.family": "sans-serif",
    "font.size": 11,
    "axes.spines.top": False,
    "axes.spines.right": False,
    "axes.grid": True,
    "grid.alpha": 0.15,
})

BLUE = "#2E86AB"
RED = "#E63946"
AMBER = "#F4A261"
GREEN = "#2A9D8F"
GRAY = "#8D99AE"

# -- Load data --
df = pd.read_csv("q2_monthly_metrics.csv")
df["month_label"] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]


# ============================================================
# Chart 1: Dual-axis — Churn Rate vs Onboarding Activation
# ============================================================
fig, ax1 = plt.subplots(figsize=(10, 5))

ax1.plot(df["month_label"], df["churn_rate_pct"], color=RED, linewidth=2.5,
         marker="o", markersize=8, label="Churn Rate (%)", zorder=5)
ax1.set_ylabel("Churn Rate (%)", color=RED, fontsize=12)
ax1.set_ylim(3.5, 8.5)
ax1.tick_params(axis="y", labelcolor=RED)

# Annotate the June spike
ax1.annotate("7.1% — highest\non record", xy=(5, 7.1), xytext=(4.2, 7.8),
             fontsize=9, color=RED, fontweight="bold",
             arrowprops=dict(arrowstyle="->", color=RED, lw=1.5))

ax2 = ax1.twinx()
ax2.plot(df["month_label"], df["onboarding_activated_pct"], color=BLUE,
         linewidth=2.5, marker="s", markersize=8, label="Activation Rate (%)",
         zorder=5)
ax2.set_ylabel("Onboarding Activation (%)", color=BLUE, fontsize=12)
ax2.set_ylim(50, 78)
ax2.tick_params(axis="y", labelcolor=BLUE)

# Shade the Q2 region
ax1.axvspan(2.5, 5.5, alpha=0.07, color=RED, label="Q2 2026")
ax1.axvline(x=2.5, color=GRAY, linestyle="--", linewidth=1, alpha=0.5)
ax1.text(2.6, 8.2, "Onboarding redesign\nships end of Q1", fontsize=8,
         color=GRAY, fontstyle="italic")

ax1.set_title("Churn and Activation Are Moving in Opposite Directions",
              fontsize=14, fontweight="bold", pad=15)
ax1.set_xlabel("")

lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc="lower left",
           framealpha=0.9, fontsize=9)

plt.tight_layout()
plt.savefig("chart1_churn_vs_activation.png", dpi=180, bbox_inches="tight")
plt.close()


# ============================================================
# Chart 2: Onboarding completion → churn outcome
# ============================================================
fig, ax = plt.subplots(figsize=(8, 5))

categories = ["Completed\nOnboarding", "Did NOT Complete\nOnboarding"]
churn_rates = [3.1, 11.4]
colors = [GREEN, RED]

bars = ax.bar(categories, churn_rates, color=colors, width=0.5, edgecolor="white",
              linewidth=1.5, zorder=5)

for bar, rate in zip(bars, churn_rates):
    ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.3,
            f"{rate}%", ha="center", fontsize=16, fontweight="bold",
            color=bar.get_facecolor())

ax.set_ylabel("Churn Rate (%)", fontsize=12)
ax.set_ylim(0, 14.5)
ax.set_title("Onboarding Is the Single Biggest Predictor of Retention",
             fontsize=13, fontweight="bold", pad=15)

ax.text(1, 13, "3.7x higher churn\nfor non-completers",
        ha="center", fontsize=11, color=RED, fontweight="bold",
        bbox=dict(boxstyle="round,pad=0.4", facecolor="#FFF0F0",
                  edgecolor=RED, alpha=0.9))

ax.text(0.5, -2.2, "62% of Q2 churned customers never completed onboarding.",
        ha="center", fontsize=10, color=GRAY, fontstyle="italic",
        transform=ax.transData)

plt.tight_layout()
plt.savefig("chart2_onboarding_churn.png", dpi=180, bbox_inches="tight")
plt.close()


# ============================================================
# Chart 3: Churn by tier — horizontal bars
# ============================================================
fig, ax = plt.subplots(figsize=(8, 4))

tiers = ["Enterprise", "Growth", "Starter"]
rates = [1.9, 5.3, 9.8]
arr_risk = ["$570K", "$680K", "$420K"]
bar_colors = [GREEN, AMBER, RED]

bars = ax.barh(tiers, rates, color=bar_colors, height=0.55, edgecolor="white",
               linewidth=1.5, zorder=5)

for bar, rate, risk in zip(bars, rates, arr_risk):
    ax.text(bar.get_width() + 0.2, bar.get_y() + bar.get_height() / 2,
            f"{rate}%  ({risk} ARR at risk)",
            va="center", fontsize=11, fontweight="bold",
            color=bar.get_facecolor())

ax.set_xlim(0, 14)
ax.set_xlabel("Q2 Churn Rate (%)", fontsize=11)
ax.set_title("Starter Tier Bears the Brunt of the Churn Increase",
             fontsize=13, fontweight="bold", pad=15)
ax.invert_yaxis()

plt.tight_layout()
plt.savefig("chart3_churn_by_tier.png", dpi=180, bbox_inches="tight")
plt.close()


# ============================================================
# Chart 4: NRR trend with danger zone
# ============================================================
fig, ax = plt.subplots(figsize=(10, 5))

ax.plot(df["month_label"], df["net_revenue_retention_pct"], color=BLUE,
        linewidth=2.5, marker="o", markersize=8, zorder=5)

ax.axhline(y=100, color=RED, linestyle="--", linewidth=1.5, alpha=0.7)
ax.fill_between(df["month_label"], 95, 100, alpha=0.08, color=RED)
ax.text(0.1, 96.5, "CONTRACTION ZONE\n(NRR < 100%)", fontsize=9, color=RED,
        fontweight="bold", alpha=0.6)

# Annotate June crossing below 100
ax.annotate("99% — first time\nbelow 100%", xy=(5, 99), xytext=(3.5, 96),
            fontsize=10, color=RED, fontweight="bold",
            arrowprops=dict(arrowstyle="->", color=RED, lw=1.5))

ax.set_ylim(95, 113)
ax.set_ylabel("Net Revenue Retention (%)", fontsize=12)
ax.set_title("Net Revenue Retention Has Crossed Below 100% — We Are Now Contracting",
             fontsize=13, fontweight="bold", pad=15)

ax.yaxis.set_major_formatter(mticker.FormatStrFormatter("%d%%"))

plt.tight_layout()
plt.savefig("chart4_nrr_trend.png", dpi=180, bbox_inches="tight")
plt.close()


# ============================================================
# Chart 5: ROI — cost of action vs inaction
# ============================================================
fig, ax = plt.subplots(figsize=(8, 5))

scenarios = ["Q2 Actual\nLoss", "Q3 Projected\nWITHOUT Action", "Q3 Projected\nWITH Action"]
values = [1.67, 2.5, 0.95]
colors = [GRAY, RED, GREEN]

bars = ax.bar(scenarios, values, color=colors, width=0.5, edgecolor="white",
              linewidth=1.5, zorder=5)

for bar, val in zip(bars, values):
    ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.07,
            f"${val}M", ha="center", fontsize=14, fontweight="bold",
            color=bar.get_facecolor())

# Arrow showing savings
ax.annotate("", xy=(2, 0.95), xytext=(1, 2.5),
            arrowprops=dict(arrowstyle="->", color=GREEN, lw=2.5,
                            connectionstyle="arc3,rad=-0.2"))
ax.text(1.9, 1.85, "$1.1–2.0M\nARR saved", fontsize=11, color=GREEN,
        fontweight="bold", ha="center")

ax.set_ylabel("ARR Impact ($ Millions)", fontsize=12)
ax.set_ylim(0, 3.2)
ax.set_title("The Cost of Inaction Far Exceeds the Cost of Intervention",
             fontsize=13, fontweight="bold", pad=15)

ax.text(2, 0.3, "Investment: ~$250K\nPayback: < 90 days",
        ha="center", fontsize=10, color=GREEN,
        bbox=dict(boxstyle="round,pad=0.4", facecolor="#F0FFF0",
                  edgecolor=GREEN, alpha=0.9))

plt.tight_layout()
plt.savefig("chart5_roi_comparison.png", dpi=180, bbox_inches="tight")
plt.close()


print("All 5 charts generated successfully:")
print("  1. chart1_churn_vs_activation.png  — Dual trend: churn vs activation")
print("  2. chart2_onboarding_churn.png     — Onboarding completion impact")
print("  3. chart3_churn_by_tier.png        — Churn by plan tier")
print("  4. chart4_nrr_trend.png            — NRR crossing below 100%")
print("  5. chart5_roi_comparison.png       — Cost of action vs inaction")
