#!/usr/bin/env python3
"""
Step 3: SentinelOne Valuation Analysis

This script applies precedent transaction multiples to SentinelOne's financials
to calculate implied valuation ranges, share prices, and takeout premiums.

Valuation Multiples (from Step 2):
- Conservative: 9.2x (Median ex-Wiz)
- Base Case: 10.0x (Mean ex-Wiz)
- Optimistic: 14.2x (75th Percentile)
"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from pathlib import Path
from datetime import datetime

# Constants
SESSION_DIR = Path("/app/sandbox/session_20260203_085757_d926b2c7d1fb")
RESULTS_DIR = SESSION_DIR / "results"
FIGURES_DIR = SESSION_DIR / "figures"

# Valuation multiples from Step 2
MULTIPLES = {
    "Conservative": 9.2,
    "Base Case": 10.0,
    "Optimistic": 14.2
}

def load_sentinelone_data():
    """Load SentinelOne's financial data from screening results."""
    print("=" * 60)
    print("Step 3: SentinelOne Valuation Analysis")
    print("=" * 60)
    print("\n[1/6] Loading financial data...")

    df = pd.read_csv(RESULTS_DIR / "financial_screening_data.csv")

    # Filter for SentinelOne (ticker: S)
    s_data = df[df["Ticker"] == "S"].iloc[0]

    financials = {
        "company": s_data["Company"],
        "ticker": s_data["Ticker"],
        "current_price": s_data["Current_Price"],
        "market_cap": s_data["Market_Cap"],
        "enterprise_value": s_data["Enterprise_Value"],
        "ltm_revenue": s_data["LTM_Revenue"],
        "revenue_growth": s_data["Revenue_Growth"],
        "ev_revenue_multiple": s_data["EV_Revenue_Multiple"]
    }

    print(f"   Company: {financials['company']} ({financials['ticker']})")
    print(f"   Current Price: ${financials['current_price']:.2f}")
    print(f"   Market Cap: ${financials['market_cap']/1e9:.2f}B")
    print(f"   Enterprise Value: ${financials['enterprise_value']/1e9:.2f}B")
    print(f"   LTM Revenue: ${financials['ltm_revenue']/1e9:.3f}B")
    print(f"   Revenue Growth: {financials['revenue_growth']*100:.1f}%")
    print(f"   Current EV/Revenue: {financials['ev_revenue_multiple']:.2f}x")

    return financials


def derive_balance_sheet_proxies(financials):
    """Derive Net Debt and Shares Outstanding from available data."""
    print("\n[2/6] Deriving balance sheet proxies...")

    # Net Debt = EV - Market Cap
    # Negative value indicates net cash position
    net_debt = financials["enterprise_value"] - financials["market_cap"]

    # Shares Outstanding = Market Cap / Current Price
    shares_outstanding = financials["market_cap"] / financials["current_price"]

    financials["net_debt"] = net_debt
    financials["shares_outstanding"] = shares_outstanding

    cash_status = "Net Cash" if net_debt < 0 else "Net Debt"
    print(f"   Net Debt: ${net_debt/1e9:.3f}B ({cash_status} of ${abs(net_debt)/1e9:.3f}B)")
    print(f"   Shares Outstanding: {shares_outstanding/1e6:.1f}M")

    return financials


def calculate_implied_valuations(financials):
    """Apply valuation multiples to calculate implied EV, share prices, and premiums."""
    print("\n[3/6] Calculating implied valuations...")

    ltm_revenue = financials["ltm_revenue"]
    net_debt = financials["net_debt"]
    shares_outstanding = financials["shares_outstanding"]
    current_price = financials["current_price"]

    valuation_results = []

    print(f"\n   LTM Revenue: ${ltm_revenue/1e9:.3f}B")
    print(f"   Valuation Multiples Applied: {list(MULTIPLES.keys())}")
    print("\n   Scenario Results:")
    print("   " + "-" * 70)

    for scenario, multiple in MULTIPLES.items():
        # Implied Enterprise Value
        implied_ev = ltm_revenue * multiple

        # Implied Market Cap = Implied EV - Net Debt
        implied_market_cap = implied_ev - net_debt

        # Implied Share Price = Implied Market Cap / Shares Outstanding
        implied_share_price = implied_market_cap / shares_outstanding

        # Takeout Premium (percentage upside vs current price)
        takeout_premium = (implied_share_price - current_price) / current_price * 100

        result = {
            "Scenario": scenario,
            "EV_Revenue_Multiple": multiple,
            "Implied_EV_B": implied_ev / 1e9,
            "Implied_Market_Cap_B": implied_market_cap / 1e9,
            "Implied_Share_Price": implied_share_price,
            "Current_Price": current_price,
            "Takeout_Premium_Pct": takeout_premium
        }
        valuation_results.append(result)

        print(f"   {scenario}:")
        print(f"      Multiple: {multiple}x | Implied EV: ${implied_ev/1e9:.2f}B | "
              f"Share Price: ${implied_share_price:.2f} | Premium: {takeout_premium:+.1f}%")

    print("   " + "-" * 70)

    return pd.DataFrame(valuation_results)


def create_football_field_chart(valuation_df, financials):
    """Generate a football field chart visualizing valuation ranges."""
    print("\n[4/6] Generating football field chart...")

    # Set up the figure
    fig, ax = plt.subplots(figsize=(12, 6))

    current_price = financials["current_price"]

    # Get valuation ranges
    conservative = valuation_df[valuation_df["Scenario"] == "Conservative"]["Implied_Share_Price"].values[0]
    base_case = valuation_df[valuation_df["Scenario"] == "Base Case"]["Implied_Share_Price"].values[0]
    optimistic = valuation_df[valuation_df["Scenario"] == "Optimistic"]["Implied_Share_Price"].values[0]

    # Colors
    colors = {
        "current": "#34495e",
        "conservative": "#3498db",
        "base": "#2ecc71",
        "optimistic": "#e74c3c",
        "range": "#95a5a6"
    }

    # Y-positions for horizontal bars
    y_positions = {
        "Precedent\nTransaction\nRange": 1,
    }

    bar_height = 0.4

    # Draw the valuation range bar (conservative to optimistic)
    ax.barh(y=1, width=optimistic - conservative, left=conservative,
            height=bar_height, color=colors["range"], alpha=0.3, edgecolor=colors["range"])

    # Draw scenario markers
    for scenario, price, color, marker in [
        ("Conservative (9.2x)", conservative, colors["conservative"], "s"),
        ("Base Case (10.0x)", base_case, colors["base"], "D"),
        ("Optimistic (14.2x)", optimistic, colors["optimistic"], "^")
    ]:
        ax.scatter(price, 1, marker=marker, s=200, c=color, zorder=5, edgecolors='white', linewidths=2)
        ax.annotate(f"${price:.2f}", (price, 1 + 0.35), ha='center', va='bottom', fontsize=10, fontweight='bold')

    # Draw current price line
    ax.axvline(x=current_price, color=colors["current"], linestyle='--', linewidth=2,
               label=f'Current Price (${current_price:.2f})')

    # Add current price annotation
    ax.annotate(f"Current\n${current_price:.2f}",
                xy=(current_price, 0.5), xytext=(current_price - 3, 0.3),
                fontsize=10, fontweight='bold', color=colors["current"],
                arrowprops=dict(arrowstyle='->', color=colors["current"], lw=1.5))

    # Formatting
    ax.set_xlim(0, max(optimistic, current_price) * 1.15)
    ax.set_ylim(0, 2)
    ax.set_yticks([1])
    ax.set_yticklabels(["Precedent\nTransaction\nRange"], fontsize=11)
    ax.set_xlabel("Share Price ($)", fontsize=12, fontweight='bold')

    # Add premium annotations
    premiums = valuation_df.set_index("Scenario")["Takeout_Premium_Pct"]
    ax.text(conservative, 0.55, f"+{premiums['Conservative']:.0f}%", ha='center', fontsize=9, color=colors["conservative"])
    ax.text(base_case, 0.55, f"+{premiums['Base Case']:.0f}%", ha='center', fontsize=9, color=colors["base"])
    ax.text(optimistic, 0.55, f"+{premiums['Optimistic']:.0f}%", ha='center', fontsize=9, color=colors["optimistic"])

    # Title
    ax.set_title("SentinelOne (S) Valuation Football Field\nImplied Share Prices Based on Precedent Transaction Multiples",
                 fontsize=14, fontweight='bold', pad=20)

    # Legend
    legend_elements = [
        mpatches.Patch(facecolor=colors["conservative"], edgecolor='white', label='Conservative (9.2x)'),
        mpatches.Patch(facecolor=colors["base"], edgecolor='white', label='Base Case (10.0x)'),
        mpatches.Patch(facecolor=colors["optimistic"], edgecolor='white', label='Optimistic (14.2x)'),
        plt.Line2D([0], [0], color=colors["current"], linestyle='--', linewidth=2, label=f'Current (${current_price:.2f})')
    ]
    ax.legend(handles=legend_elements, loc='upper right', fontsize=9, framealpha=0.9)

    # Add summary box
    summary_text = (f"LTM Revenue: ${financials['ltm_revenue']/1e9:.2f}B\n"
                   f"Current EV/Rev: {financials['ev_revenue_multiple']:.1f}x\n"
                   f"Implied Range: ${conservative:.2f} - ${optimistic:.2f}")
    ax.text(0.02, 0.98, summary_text, transform=ax.transAxes, fontsize=9,
            verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))

    # Grid and spine styling
    ax.grid(axis='x', alpha=0.3)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.spines['left'].set_visible(False)

    plt.tight_layout()

    # Save figure
    output_path = FIGURES_DIR / "valuation_football_field.png"
    plt.savefig(output_path, dpi=300, bbox_inches='tight', facecolor='white')
    plt.close()

    print(f"   Saved: {output_path}")
    return output_path


def save_valuation_metrics(valuation_df, financials):
    """Save detailed valuation metrics to CSV."""
    print("\n[5/6] Saving valuation metrics...")

    # Add additional context columns
    valuation_df["Company"] = financials["company"]
    valuation_df["Ticker"] = financials["ticker"]
    valuation_df["LTM_Revenue_B"] = financials["ltm_revenue"] / 1e9
    valuation_df["Net_Debt_B"] = financials["net_debt"] / 1e9
    valuation_df["Shares_Outstanding_M"] = financials["shares_outstanding"] / 1e6
    valuation_df["Analysis_Date"] = datetime.now().isoformat()

    # Reorder columns for clarity
    column_order = [
        "Company", "Ticker", "Scenario", "EV_Revenue_Multiple",
        "LTM_Revenue_B", "Implied_EV_B", "Net_Debt_B",
        "Implied_Market_Cap_B", "Shares_Outstanding_M",
        "Implied_Share_Price", "Current_Price", "Takeout_Premium_Pct",
        "Analysis_Date"
    ]
    valuation_df = valuation_df[column_order]

    output_path = RESULTS_DIR / "sentinelone_valuation.csv"
    valuation_df.to_csv(output_path, index=False)

    print(f"   Saved: {output_path}")
    print(f"   Columns: {list(valuation_df.columns)}")

    return output_path


def update_screening_summary(valuation_df, financials):
    """Append Valuation Analysis section to screening_summary.md."""
    print("\n[6/6] Updating screening summary...")

    summary_path = RESULTS_DIR / "screening_summary.md"

    # Build the new section content
    valuation_section = """
---

## Step 3: SentinelOne Valuation Analysis

### Objective
Apply precedent transaction multiples to SentinelOne's financials to calculate implied enterprise values, share prices, and potential takeout premiums.

### Input Data
| Metric | Value |
|--------|-------|
| LTM Revenue | ${ltm_rev:.2f}B |
| Current Share Price | ${current_price:.2f} |
| Market Cap | ${market_cap:.2f}B |
| Enterprise Value | ${ev:.2f}B |
| Net Debt (Cash) | ${net_debt:.3f}B |
| Shares Outstanding | {shares:.1f}M |
| Current EV/Revenue | {ev_rev:.2f}x |

### Valuation Scenarios

Using the multiples derived from precedent transaction analysis (Step 2):

| Scenario | Multiple | Implied EV | Implied Share Price | Takeout Premium |
|----------|----------|------------|---------------------|-----------------|
{scenario_rows}

### Visual Summary
![Football Field Chart](../figures/valuation_football_field.png)

### Key Findings

1. **Current Valuation Discount**: SentinelOne trades at {ev_rev:.1f}x EV/Revenue, significantly below the precedent transaction median of 9.2x - 10.0x, suggesting potential undervaluation relative to takeout peers.

2. **Takeout Premium Range**: Based on precedent multiples, a potential acquirer would likely pay:
   - **Conservative Case**: ${conservative_price:.2f}/share (+{conservative_prem:.0f}% premium)
   - **Base Case**: ${base_price:.2f}/share (+{base_prem:.0f}% premium)
   - **Optimistic Case**: ${optimistic_price:.2f}/share (+{optimistic_prem:.0f}% premium)

3. **Implied Enterprise Value**: The EV range spans ${conservative_ev:.1f}B to ${optimistic_ev:.1f}B, representing a {ev_upside_low:.0f}% to {ev_upside_high:.0f}% increase over current trading levels.

4. **Strategic Premium Potential**: Given SentinelOne's strong growth profile ({growth:.1f}% YoY) and AI-native security platform, a strategic acquirer (similar to Cisco/Splunk or Google/Mandiant) could justify multiples toward the upper end of the range.

### Outputs Generated
- `results/sentinelone_valuation.csv` - Detailed valuation metrics by scenario
- `figures/valuation_football_field.png` - Visual comparison of valuation ranges

### Next Steps
- **Step 4**: Acquirer Financial Profile Analysis - Assess potential acquirers' capacity to fund the transaction
- **Step 5**: Accretion/Dilution Analysis - Model deal impact on acquirer EPS

""".format(
        ltm_rev=financials["ltm_revenue"]/1e9,
        current_price=financials["current_price"],
        market_cap=financials["market_cap"]/1e9,
        ev=financials["enterprise_value"]/1e9,
        net_debt=financials["net_debt"]/1e9,
        shares=financials["shares_outstanding"]/1e6,
        ev_rev=financials["ev_revenue_multiple"],
        scenario_rows="\n".join([
            f"| {row['Scenario']} | {row['EV_Revenue_Multiple']}x | ${row['Implied_EV_B']:.2f}B | ${row['Implied_Share_Price']:.2f} | +{row['Takeout_Premium_Pct']:.0f}% |"
            for _, row in valuation_df.iterrows()
        ]),
        conservative_price=valuation_df[valuation_df["Scenario"]=="Conservative"]["Implied_Share_Price"].values[0],
        conservative_prem=valuation_df[valuation_df["Scenario"]=="Conservative"]["Takeout_Premium_Pct"].values[0],
        base_price=valuation_df[valuation_df["Scenario"]=="Base Case"]["Implied_Share_Price"].values[0],
        base_prem=valuation_df[valuation_df["Scenario"]=="Base Case"]["Takeout_Premium_Pct"].values[0],
        optimistic_price=valuation_df[valuation_df["Scenario"]=="Optimistic"]["Implied_Share_Price"].values[0],
        optimistic_prem=valuation_df[valuation_df["Scenario"]=="Optimistic"]["Takeout_Premium_Pct"].values[0],
        conservative_ev=valuation_df[valuation_df["Scenario"]=="Conservative"]["Implied_EV_B"].values[0],
        optimistic_ev=valuation_df[valuation_df["Scenario"]=="Optimistic"]["Implied_EV_B"].values[0],
        ev_upside_low=((valuation_df[valuation_df["Scenario"]=="Conservative"]["Implied_EV_B"].values[0]*1e9) / financials["enterprise_value"] - 1) * 100,
        ev_upside_high=((valuation_df[valuation_df["Scenario"]=="Optimistic"]["Implied_EV_B"].values[0]*1e9) / financials["enterprise_value"] - 1) * 100,
        growth=financials["revenue_growth"]*100
    )

    # Read existing content and append
    with open(summary_path, 'r') as f:
        existing_content = f.read()

    with open(summary_path, 'w') as f:
        f.write(existing_content + valuation_section)

    print(f"   Updated: {summary_path}")
    print("   Added section: 'Step 3: SentinelOne Valuation Analysis'")

    return summary_path


def main():
    """Execute the complete valuation analysis workflow."""
    print("\n" + "=" * 60)
    print("STARTING STEP 3: SENTINELONE VALUATION ANALYSIS")
    print("=" * 60)

    # Step 1: Load data
    financials = load_sentinelone_data()

    # Step 2: Derive balance sheet proxies
    financials = derive_balance_sheet_proxies(financials)

    # Step 3: Calculate implied valuations
    valuation_df = calculate_implied_valuations(financials)

    # Step 4: Generate football field chart
    create_football_field_chart(valuation_df, financials)

    # Step 5: Save valuation metrics to CSV
    save_valuation_metrics(valuation_df, financials)

    # Step 6: Update screening summary
    update_screening_summary(valuation_df, financials)

    # Final summary
    print("\n" + "=" * 60)
    print("STEP 3 COMPLETE")
    print("=" * 60)
    print("\nKey Results:")
    for _, row in valuation_df.iterrows():
        print(f"  {row['Scenario']}: ${row['Implied_Share_Price']:.2f} (+{row['Takeout_Premium_Pct']:.0f}% premium)")
    print("\nOutputs:")
    print(f"  - {RESULTS_DIR}/sentinelone_valuation.csv")
    print(f"  - {FIGURES_DIR}/valuation_football_field.png")
    print(f"  - {RESULTS_DIR}/screening_summary.md (updated)")

    return valuation_df, financials


if __name__ == "__main__":
    valuation_df, financials = main()
