"""
Build an SDR Efficiency Diagnostic model in Google Sheets.

Question answered: What is ROI of SDR investment, where are leverage points?
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Dict, List, Optional

from .period_helper import PeriodConfig, build_period_table


def _col_letter(idx: int) -> str:
    """Convert zero-based index to Excel-style column letter."""
    result = ""
    idx_val = idx
    while True:
        idx_val, rem = divmod(idx_val, 26)
        result = chr(ord("A") + rem) + result
        if idx_val == 0:
            break
        idx_val -= 1
    return result


@dataclass
class SDRInputs:
    """Inputs for the SDR Efficiency Diagnostic model."""
    sdr_count: int = 5
    meetings_per_sdr_month: int = 12
    meeting_to_opp_rate: float = 0.40
    opp_to_win_rate: float = 0.25
    avg_deal_size: float = 100000.0
    sdr_cost_month: float = 8000.0
    sales_cycle_months: int = 3
    ae_capacity_opps_month: Optional[int] = None  # Optional AE bottleneck check
    sensitivity_range: float = 0.20
    sensitivity_step: float = 0.10
    enable_plus_one_sdr: bool = True
    enable_conversion_improvement: bool = True
    # Period settings
    first_fy: int = 26
    fy_start_month: int = 1
    planning_years: int = 1  # 1–3 fiscal years to plan
    yoy_growth_pct: float = 0.0
    as_of_date: str = ""
    # Idempotency handling
    tab_suffix: str = ""  # e.g., "_v2" to append to tab names
    idempotency_action: str = ""  # "replace" or "suffix"

    @property
    def horizon_periods(self) -> int:
        return self.planning_years * 4

    def __post_init__(self) -> None:
        if self.sdr_count < 1:
            raise ValueError("sdr_count must be at least 1")

        if self.meetings_per_sdr_month < 1:
            raise ValueError("meetings_per_sdr_month must be at least 1")

        if self.meeting_to_opp_rate <= 0 or self.meeting_to_opp_rate > 1:
            raise ValueError("meeting_to_opp_rate must be between 0 and 1")

        if self.opp_to_win_rate <= 0 or self.opp_to_win_rate > 1:
            raise ValueError("opp_to_win_rate must be between 0 and 1")

        if self.fy_start_month < 1 or self.fy_start_month > 12:
            raise ValueError("fy_start_month must be between 1 and 12")


def _assumptions_row_map() -> Dict[str, int]:
    """Compute 1-based sheet row numbers for SDR assumptions cells.

    Layout mirrors _build_assumptions_rows exactly.
    """
    r = 1
    # README section (6 rows + blank)
    r += 6  # header, what, assumptions, note, FY convention, version
    r += 1  # blank
    # SDR METRICS section
    r += 1  # section header
    pos: Dict[str, int] = {}
    pos["sdr_count"] = r; r += 1
    pos["meetings_per_sdr_month"] = r; r += 1
    pos["meeting_to_opp_rate"] = r; r += 1
    pos["sdr_cost_month"] = r; r += 1
    r += 1  # blank
    # REVENUE METRICS section
    r += 1  # section header
    pos["opp_to_win_rate"] = r; r += 1
    pos["avg_deal_size"] = r; r += 1
    pos["sales_cycle_months"] = r; r += 1
    r += 1  # blank
    # CAPACITY section
    r += 1  # section header
    pos["ae_capacity_opps_month"] = r; r += 1
    r += 1  # blank
    # SENSITIVITY SETTINGS section
    r += 1  # section header
    pos["sensitivity_range"] = r; r += 1
    pos["sensitivity_step"] = r; r += 1
    pos["plus_one_sdr"] = r; r += 1
    pos["conversion_improvement"] = r; r += 1
    r += 1  # blank
    # PERIOD SETTINGS section
    r += 1  # section header
    pos["first_fy"] = r; r += 1
    pos["fy_start_month"] = r; r += 1
    pos["planning_years"] = r; r += 1
    pos["yoy_growth_pct"] = r; r += 1
    pos["as_of_date"] = r
    return pos


def _calc_row_map() -> Dict[str, int]:
    """Compute 1-based sheet row numbers for SDR calc cells."""
    r = 1
    r += 1  # header
    r += 1  # blank
    pos: Dict[str, int] = {}

    r += 1  # ACTIVITY METRICS section header
    pos["total_meetings"] = r; r += 1
    pos["opps_generated"] = r; r += 1
    pos["deals_won_steady"] = r; r += 1
    pos["revenue_steady"] = r; r += 1
    r += 1  # blank

    r += 1  # YEAR 1 REALIZATION section header
    pos["year_1_factor"] = r; r += 1
    pos["year_1_deals"] = r; r += 1
    pos["year_1_revenue"] = r; r += 1
    r += 1  # blank

    r += 1  # COST METRICS section header
    pos["total_cost"] = r; r += 1
    pos["cost_per_meeting"] = r; r += 1
    pos["cost_per_opp"] = r; r += 1
    pos["cost_per_deal"] = r; r += 1
    pos["cost_pct_revenue"] = r; r += 1
    r += 1  # blank

    r += 1  # ROI ANALYSIS section header
    pos["revenue_per_sdr"] = r; r += 1
    pos["revenue_multiple"] = r; r += 1
    r += 1  # blank

    r += 1  # Plus 1 SDR Analysis section header
    pos["plus_one_meetings"] = r; r += 1
    pos["plus_one_opps"] = r; r += 1
    pos["plus_one_deals"] = r; r += 1
    pos["plus_one_revenue"] = r; r += 1
    pos["plus_one_profit"] = r; r += 1
    pos["plus_one_roi"] = r; r += 1
    r += 1  # blank

    r += 1  # SENSITIVITY TABLE section header
    r += 1  # table header
    pos["meetings_sensitivity"] = r; r += 1
    pos["meeting_to_opp_sensitivity"] = r; r += 1
    pos["opp_to_win_sensitivity"] = r; r += 1
    pos["deal_size_sensitivity"] = r; r += 1
    r += 1  # blank

    r += 1  # AE BOTTLENECK ANALYSIS section header
    pos["sdr_opp_output"] = r; r += 1
    pos["ae_capacity"] = r; r += 1
    pos["wasted_opps"] = r; r += 1
    pos["revenue_lost"] = r; r += 1
    pos["bottleneck_status"] = r
    return pos


def _quote_tab(tab_name: str) -> str:
    """Escape single quotes in tab names for sheet references."""
    escaped = tab_name.replace("'", "''")
    return f"'{escaped}'"


def _sheet_cell(tab_name: str, cell_ref: str) -> str:
    """Build a quoted sheet cell reference."""
    return f"{_quote_tab(tab_name)}!{cell_ref}"


def _hex_to_color(hex_value: str) -> Dict[str, float]:
    """Convert hex color to RGB normalized to 0-1."""
    hex_value = hex_value.lstrip("#")
    r = int(hex_value[0:2], 16) / 255.0
    g = int(hex_value[2:4], 16) / 255.0
    b = int(hex_value[4:6], 16) / 255.0
    return {"red": r, "green": g, "blue": b}


def build_sdr_diagnostic(
    inputs: SDRInputs,
    sheets_service,
    spreadsheet_id: Optional[str] = None,
    title: str = "SDR Efficiency Diagnostic",
) -> Dict[str, Any]:
    """
    Build the SDR Efficiency Diagnostic model.

    Creates 3 tabs:
    - SDR_Assumptions: User inputs with readme panel
    - SDR_Calc: Calculations and sensitivity analysis
    - SDR_Dashboard: Key outputs and ROI metrics

    Args:
        inputs: SDRInputs with all model parameters
        sheets_service: Google Sheets API service client
        spreadsheet_id: Optional existing spreadsheet to update
        title: Title for new spreadsheet if created

    Returns:
        Dict with spreadsheet_id, url, tabs_created, validation status
    """
    # Apply tab suffix if provided (for idempotency with suffix mode)
    suffix = inputs.tab_suffix or ""
    assumptions_tab = f"SDR_Assumptions{suffix}"
    calc_tab = f"SDR_Calc{suffix}"
    dashboard_tab = f"SDR_Dashboard{suffix}"

    # Determine if we should replace existing tabs
    replace_existing = inputs.idempotency_action == "replace"

    # Generate period labels for quarterly view
    period_config = PeriodConfig(
        first_fy=inputs.first_fy,
        fy_start_month=inputs.fy_start_month,
        granularity="quarterly",
        horizon_periods=inputs.horizon_periods,
    )
    periods = build_period_table(period_config)

    # Create or get spreadsheet
    if spreadsheet_id is None:
        create_resp = sheets_service.spreadsheets().create(
            body={"properties": {"title": title}}
        ).execute()
        spreadsheet_id = create_resp["spreadsheetId"]
        created = True
    else:
        created = False

    # Ensure tabs exist (replace if idempotency action is "replace")
    _ensure_sheet(sheets_service, spreadsheet_id, assumptions_tab, replace=replace_existing)
    _ensure_sheet(sheets_service, spreadsheet_id, calc_tab, replace=replace_existing)
    _ensure_sheet(sheets_service, spreadsheet_id, dashboard_tab, replace=replace_existing)

    # Write Assumptions tab
    assumptions_rows = _build_assumptions_rows(inputs)
    _write_rows(sheets_service, spreadsheet_id, assumptions_tab, assumptions_rows)

    # Write Calc tab
    calc_rows = _build_calc_rows(inputs, assumptions_tab)
    _write_rows(sheets_service, spreadsheet_id, calc_tab, calc_rows)

    fy_labels: List[str] = []
    for period in periods:
        label = f"FY{period.fy}"
        if not fy_labels or fy_labels[-1] != label:
            fy_labels.append(label)

    # Write Dashboard tab
    dashboard_rows = _build_dashboard_rows(inputs, calc_tab, assumptions_tab, fy_labels=fy_labels)
    _write_rows(sheets_service, spreadsheet_id, dashboard_tab, dashboard_rows)

    # Apply styling
    _apply_sdr_style(sheets_service, spreadsheet_id, assumptions_tab, calc_tab, dashboard_tab)

    # Validate
    validation = _validate_sdr(sheets_service, spreadsheet_id, calc_tab, inputs)

    url = f"https://docs.google.com/spreadsheets/d/{spreadsheet_id}"

    return {
        "spreadsheet_id": spreadsheet_id,
        "url": url,
        "tabs_created": [assumptions_tab, calc_tab, dashboard_tab],
        "created": created,
        "validation": validation,
    }


def _ensure_sheet(service, spreadsheet_id: str, sheet_name: str, replace: bool = False) -> int:
    """Ensure a sheet exists, creating it if needed. Returns sheet ID.

    Args:
        service: Sheets API service
        spreadsheet_id: Spreadsheet ID
        sheet_name: Name of the sheet
        replace: If True, delete existing sheet first
    """
    try:
        ss = service.spreadsheets().get(spreadsheetId=spreadsheet_id).execute()
        for sheet in ss.get("sheets", []):
            if sheet["properties"]["title"] == sheet_name:
                if replace:
                    # Delete existing sheet
                    sheet_id = sheet["properties"]["sheetId"]
                    service.spreadsheets().batchUpdate(
                        spreadsheetId=spreadsheet_id,
                        body={
                            "requests": [
                                {"deleteSheet": {"sheetId": sheet_id}}
                            ]
                        }
                    ).execute()
                    break  # Fall through to create new sheet
                else:
                    return sheet["properties"]["sheetId"]
    except Exception:
        pass

    # Create the sheet
    resp = service.spreadsheets().batchUpdate(
        spreadsheetId=spreadsheet_id,
        body={
            "requests": [
                {"addSheet": {"properties": {"title": sheet_name}}}
            ]
        }
    ).execute()

    return resp["replies"][0]["addSheet"]["properties"]["sheetId"]


def _write_rows(service, spreadsheet_id: str, sheet_name: str, rows: List[List[Any]]) -> None:
    """Write rows to a sheet."""
    if not rows:
        return

    # Determine range
    num_cols = max(len(row) for row in rows)
    end_col = _col_letter(num_cols - 1)
    range_str = f"{sheet_name}!A1:{end_col}{len(rows)}"

    # Pad rows to same length
    padded_rows = []
    for row in rows:
        padded = list(row) + [""] * (num_cols - len(row))
        padded_rows.append(padded)

    service.spreadsheets().values().update(
        spreadsheetId=spreadsheet_id,
        range=range_str,
        valueInputOption="USER_ENTERED",
        body={"values": padded_rows}
    ).execute()


def _build_assumptions_rows(inputs: SDRInputs) -> List[List[Any]]:
    """Build the Assumptions tab content."""
    rows = []

    # README section
    rows.append(["SDR EFFICIENCY DIAGNOSTIC - ASSUMPTIONS"])
    rows.append(["What this model answers:", "What is ROI of SDR investment, where are leverage points?"])
    rows.append(["Assumptions you can change:", "SDR count, meetings, conversion rates, costs"])
    rows.append(["Note:", "Dashboard separates steady-state economics from Year 1 realization; multi-year mode uses realized Year 1 then steady-state thereafter"])
    rows.append(["FY convention:", "FY label uses the fiscal year end year (e.g., FY26 ends in 2026)"])
    rows.append(["Version:", "v1.3 (2026-03-13) - Multi-year view now uses Year 1 realization and steady-state annualization for later fiscal years."])
    rows.append([])

    # SDR METRICS section
    rows.append(["SDR METRICS"])
    rows.append(["SDR Headcount", inputs.sdr_count])
    rows.append(["Meetings/SDR/Month", inputs.meetings_per_sdr_month])
    rows.append(["Meeting-to-Opp Rate", inputs.meeting_to_opp_rate])
    rows.append(["SDR Cost ($/month)", inputs.sdr_cost_month])
    rows.append([])

    # REVENUE METRICS section
    rows.append(["REVENUE METRICS"])
    rows.append(["Opp-to-Win Rate", inputs.opp_to_win_rate])
    rows.append(["Avg Deal Size", inputs.avg_deal_size])
    rows.append(["Sales Cycle (months)", inputs.sales_cycle_months])
    rows.append([])

    # CAPACITY section
    rows.append(["CAPACITY"])
    rows.append(["AE Capacity (opps/month)", inputs.ae_capacity_opps_month if inputs.ae_capacity_opps_month else ""])
    rows.append([])

    # SENSITIVITY section
    rows.append(["SENSITIVITY SETTINGS"])
    rows.append(["Sensitivity Range", inputs.sensitivity_range])
    rows.append(["Sensitivity Step", inputs.sensitivity_step])
    rows.append(["Plus 1 SDR Analysis", "Yes" if inputs.enable_plus_one_sdr else "No"])
    rows.append(["Conversion Improvement", "Yes" if inputs.enable_conversion_improvement else "No"])
    rows.append([])

    # PERIOD SETTINGS section
    rows.append(["PERIOD SETTINGS"])
    rows.append(["First Fiscal Year", inputs.first_fy])
    rows.append(["FY Start Month", inputs.fy_start_month])
    rows.append(["Planning Years", inputs.planning_years])
    rows.append(["YoY Growth %", inputs.yoy_growth_pct])
    rows.append(["As-Of Date", inputs.as_of_date or ""])

    return rows


def _build_calc_rows(inputs: SDRInputs, assumptions_tab: str) -> List[List[Any]]:
    """Build the Calc tab with formulas."""
    rows = []
    rm = _assumptions_row_map()

    def _a(key: str) -> str:
        """Return absolute $B$N reference into assumptions tab."""
        return _sheet_cell(assumptions_tab, f"$B${rm[key]}")

    # First-year realization factor under uniform monthly opp creation.
    year_1_factor = f"MAX(0,MIN(1,(12-{_a('sales_cycle_months')})/12))"
    steady_deals = f"{_a('sdr_count')}*{_a('meetings_per_sdr_month')}*{_a('meeting_to_opp_rate')}*{_a('opp_to_win_rate')}"

    # Header
    rows.append(["SDR EFFICIENCY CALCULATIONS"])
    rows.append([])

    # ACTIVITY METRICS section (Monthly)
    rows.append(["ACTIVITY METRICS (Monthly)"])
    rows.append(["Total Meetings/Month", f"={_a('sdr_count')}*{_a('meetings_per_sdr_month')}"])
    rows.append(["Opps Generated/Month", f"={_a('sdr_count')}*{_a('meetings_per_sdr_month')}*{_a('meeting_to_opp_rate')}"])
    rows.append(["Deals Won/Month (steady-state)", f"={steady_deals}"])
    rows.append(["Revenue/Month (steady-state)", f"=B6*{_a('avg_deal_size')}"])
    rows.append([])

    # YEAR 1 REALIZATION section
    rows.append(["YEAR 1 REALIZATION"])
    rows.append(["Year 1 Realization Factor", f"={year_1_factor}"])
    rows.append(["Year 1 Deals Won/Month (blended)", "=B6*B10"])
    rows.append(["Year 1 Revenue/Month (blended)", "=B7*B10"])
    rows.append([])

    # COST METRICS section
    rows.append(["COST METRICS"])
    rows.append(["Total SDR Cost/Month", f"={_a('sdr_count')}*{_a('sdr_cost_month')}"])
    rows.append(["Cost per Meeting", "=IFERROR(B15/B4,0)"])
    rows.append(["Cost per Opp", "=IFERROR(B15/B5,0)"])
    rows.append(["Cost per Deal", "=IFERROR(B15/B6,0)"])
    rows.append(["SDR Cost as % of Revenue", "=IFERROR(B15/B7,0)"])
    rows.append([])

    # ROI ANALYSIS section
    rows.append(["ROI ANALYSIS"])
    rows.append(["Revenue per SDR", f"=IFERROR(B7/{_a('sdr_count')},0)"])
    rows.append(["Revenue Multiple", "=IFERROR(B7/B15,0)"])
    rows.append([])

    # MARGINAL ANALYSIS section
    rows.append(["Plus 1 SDR Analysis"])
    rows.append(["Plus 1 SDR: Additional Meetings", f"={_a('meetings_per_sdr_month')}"])
    rows.append(["Plus 1 SDR: Additional Opps", f"={_a('meetings_per_sdr_month')}*{_a('meeting_to_opp_rate')}"])
    rows.append(["Plus 1 SDR: Additional Deals", f"={_a('meetings_per_sdr_month')}*{_a('meeting_to_opp_rate')}*{_a('opp_to_win_rate')}"])
    rows.append(["Plus 1 SDR: Additional Revenue", f"=B28*{_a('avg_deal_size')}"])
    rows.append(["Plus 1 SDR: Marginal Profit", f"=B29-{_a('sdr_cost_month')}"])
    rows.append(["Plus 1 SDR: Marginal ROI", f"=IFERROR(B30/{_a('sdr_cost_month')},0)"])
    rows.append([])

    # SENSITIVITY TABLE section
    rows.append(["SENSITIVITY TABLE"])
    rows.append(["Variable", "Range -", "Step -", "Base", "Step +", "Range +"])

    # Revenue formula base: SDR * Meetings * MtOpp * OppWin * ASP
    sdr = _a('sdr_count')
    mtg = _a('meetings_per_sdr_month')
    mtopp = _a('meeting_to_opp_rate')
    oppwin = _a('opp_to_win_rate')
    asp = _a('avg_deal_size')
    sens_range = _a('sensitivity_range')
    sens_step = _a('sensitivity_step')
    low_range = f"(1-{sens_range})"
    low_step = f"(1-{sens_step})"
    high_step = f"(1+{sens_step})"
    high_range = f"(1+{sens_range})"

    # Meetings/SDR sensitivity
    rows.append([
        "Meetings/SDR",
        f"={sdr}*{mtg}*{low_range}*{mtopp}*{oppwin}*{asp}",
        f"={sdr}*{mtg}*{low_step}*{mtopp}*{oppwin}*{asp}",
        "=B7",
        f"={sdr}*{mtg}*{high_step}*{mtopp}*{oppwin}*{asp}",
        f"={sdr}*{mtg}*{high_range}*{mtopp}*{oppwin}*{asp}",
    ])

    # Meeting->Opp sensitivity
    rows.append([
        "Meeting->Opp",
        f"={sdr}*{mtg}*{mtopp}*{low_range}*{oppwin}*{asp}",
        f"={sdr}*{mtg}*{mtopp}*{low_step}*{oppwin}*{asp}",
        "=B7",
        f"={sdr}*{mtg}*{mtopp}*{high_step}*{oppwin}*{asp}",
        f"={sdr}*{mtg}*{mtopp}*{high_range}*{oppwin}*{asp}",
    ])

    # Opp->Win sensitivity
    rows.append([
        "Opp->Win",
        f"={sdr}*{mtg}*{mtopp}*{oppwin}*{low_range}*{asp}",
        f"={sdr}*{mtg}*{mtopp}*{oppwin}*{low_step}*{asp}",
        "=B7",
        f"={sdr}*{mtg}*{mtopp}*{oppwin}*{high_step}*{asp}",
        f"={sdr}*{mtg}*{mtopp}*{oppwin}*{high_range}*{asp}",
    ])

    # Deal Size sensitivity
    rows.append([
        "Deal Size",
        f"={sdr}*{mtg}*{mtopp}*{oppwin}*{asp}*{low_range}",
        f"={sdr}*{mtg}*{mtopp}*{oppwin}*{asp}*{low_step}",
        "=B7",
        f"={sdr}*{mtg}*{mtopp}*{oppwin}*{asp}*{high_step}",
        f"={sdr}*{mtg}*{mtopp}*{oppwin}*{asp}*{high_range}",
    ])
    rows.append([])

    # AE BOTTLENECK section
    rows.append(["AE BOTTLENECK ANALYSIS"])
    rows.append(["SDR Opp Output/Month", "=B5"])
    rows.append(["AE Capacity/Month", f"={_a('ae_capacity_opps_month')}"])
    rows.append(["Wasted Opps/Month", f"=IF({_a('ae_capacity_opps_month')}<>\"\",MAX(0,B41-B42),0)"])
    rows.append(["Revenue Lost/Month", f"=B43*{_a('opp_to_win_rate')}*{_a('avg_deal_size')}"])
    rows.append(["Bottleneck Status", f'=IF({_a("ae_capacity_opps_month")}="","N/A",IF(B43>0,"BOTTLENECK","OK"))'])

    return rows


def _build_dashboard_rows(
    inputs: SDRInputs,
    calc_tab: str,
    assumptions_tab: str,
    fy_labels: Optional[List[str]] = None,
) -> List[List[Any]]:
    """Build the Dashboard tab with key metrics."""
    rows = []
    calc_rm = _calc_row_map()
    assumptions_rm = _assumptions_row_map()

    def _c(key: str) -> str:
        return _sheet_cell(calc_tab, f"B{calc_rm[key]}")

    def _a(key: str) -> str:
        return _sheet_cell(assumptions_tab, f"$B${assumptions_rm[key]}")

    if fy_labels is None:
        fy_labels = [f"FY{inputs.first_fy + offset}" for offset in range(max(1, inputs.planning_years))]

    # Header
    rows.append(["SDR EFFICIENCY DASHBOARD"])
    rows.append([])

    # KEY METRICS
    rows.append(["KEY METRICS"])
    rows.append(["Metric", "Monthly", "Quarterly", "Annual"])
    rows.append(["Total Meetings", f"={_c('total_meetings')}", f"={_c('total_meetings')}*3", f"={_c('total_meetings')}*12"])
    rows.append(["Opps Generated", f"={_c('opps_generated')}", f"={_c('opps_generated')}*3", f"={_c('opps_generated')}*12"])
    rows.append(["Deals Won (steady-state)", f"={_c('deals_won_steady')}", f"={_c('deals_won_steady')}*3", f"={_c('deals_won_steady')}*12"])
    rows.append(["Revenue (steady-state)", f"={_c('revenue_steady')}", f"={_c('revenue_steady')}*3", f"={_c('revenue_steady')}*12"])
    rows.append([])

    # YEAR 1 REALIZATION
    rows.append(["YEAR 1 REALIZATION"])
    rows.append(["Metric", "Monthly", "Quarterly", "Annual"])
    rows.append(["Deals Won (Year 1 blended)", f"={_c('year_1_deals')}", f"={_c('year_1_deals')}*3", f"={_c('year_1_deals')}*12"])
    rows.append(["Revenue (Year 1 blended)", f"={_c('year_1_revenue')}", f"={_c('year_1_revenue')}*3", f"={_c('year_1_revenue')}*12"])
    rows.append([])

    # FISCAL YEAR PLAN
    rows.append(["FISCAL YEAR PLAN"])
    fy_header = ["Metric"]
    fy_header.extend(fy_labels)
    rows.append(fy_header)

    annual_deals_row = ["Deals Won (annual plan)"]
    annual_revenue_row = ["Revenue (annual plan)"]
    growth_ref = _a("yoy_growth_pct")
    for offset, _ in enumerate(fy_labels):
        if offset == 0:
            annual_deals_row.append(f"={_c('year_1_deals')}*12")
            annual_revenue_row.append(f"={_c('year_1_revenue')}*12")
        else:
            growth_factor = f"(1+{growth_ref})^{offset}"
            annual_deals_row.append(f"={_c('deals_won_steady')}*12*{growth_factor}")
            annual_revenue_row.append(f"={_c('revenue_steady')}*12*{growth_factor}")
    rows.append(annual_deals_row)
    rows.append(annual_revenue_row)
    rows.append([])

    # COST EFFICIENCY
    rows.append(["COST EFFICIENCY"])
    rows.append(["Metric", "Value"])
    rows.append(["Cost per Meeting", f"={_c('cost_per_meeting')}"])
    rows.append(["Cost per Opp", f"={_c('cost_per_opp')}"])
    rows.append(["Cost per Deal", f"={_c('cost_per_deal')}"])
    rows.append(["SDR Cost as % of Revenue", f"={_c('cost_pct_revenue')}"])
    rows.append([])

    # ROI
    rows.append(["ROI METRICS"])
    rows.append(["Revenue per SDR (monthly)", f"={_c('revenue_per_sdr')}"])
    rows.append(["Revenue Multiple", f"={_c('revenue_multiple')}"])
    rows.append([])

    # MARGINAL ANALYSIS
    rows.append(["Plus 1 SDR Impact"])
    rows.append(["Additional Monthly Revenue", f"={_c('plus_one_revenue')}"])
    rows.append(["Marginal Monthly Profit", f"={_c('plus_one_profit')}"])
    rows.append(["Marginal ROI", f"={_c('plus_one_roi')}"])
    rows.append([])

    # BOTTLENECK STATUS
    rows.append(["AE BOTTLENECK CHECK"])
    rows.append(["Status", f"={_c('bottleneck_status')}"])
    rows.append(["Revenue at Risk (monthly)", f"={_c('revenue_lost')}"])
    rows.append([])

    # SANITY CHECK section (self-diagnostic)
    rows.append(["SANITY CHECK"])
    # Check: Revenue = Meetings × MtOpp × OppWin × ASP (within tolerance)
    # Calc: B4=Meetings, B7=Revenue; Assumptions: B9=MtOpp, B13=OppWin, B14=ASP
    calc_mtgs = _c("total_meetings")
    calc_rev = _c("revenue_steady")
    mt_opp = _a("meeting_to_opp_rate")
    opp_win = _a("opp_to_win_rate")
    asp = _a("avg_deal_size")
    expected_rev = f"{calc_mtgs}*{mt_opp}*{opp_win}*{asp}"
    rows.append(["Check (Steady Revenue = Mtg x Rates x ASP)", f'=IF(ABS({calc_rev}-({expected_rev}))<0.01,"OK","CHECK")'])

    return rows


def _get_sheet_id(service, spreadsheet_id: str, sheet_name: str) -> int:
    """Get the sheet ID for a named sheet."""
    ss = service.spreadsheets().get(spreadsheetId=spreadsheet_id).execute()
    for sheet in ss.get("sheets", []):
        if sheet["properties"]["title"] == sheet_name:
            return sheet["properties"]["sheetId"]
    raise ValueError(f"Sheet {sheet_name} not found")


def _apply_sdr_style(
    service,
    spreadsheet_id: str,
    assumptions_tab: str,
    calc_tab: str,
    dashboard_tab: str
) -> None:
    """Apply professional formatting to all tabs."""
    requests = []

    # Style each tab
    for tab_name in [assumptions_tab, calc_tab, dashboard_tab]:
        try:
            sheet_id = _get_sheet_id(service, spreadsheet_id, tab_name)
        except ValueError:
            continue

        # Freeze first row
        requests.append({
            "updateSheetProperties": {
                "properties": {
                    "sheetId": sheet_id,
                    "gridProperties": {
                        "frozenRowCount": 1,
                    }
                },
                "fields": "gridProperties.frozenRowCount",
            }
        })

        # Header styling (row 1)
        requests.append({
            "repeatCell": {
                "range": {
                    "sheetId": sheet_id,
                    "startRowIndex": 0,
                    "endRowIndex": 1,
                    "startColumnIndex": 0,
                    "endColumnIndex": 7,
                },
                "cell": {
                    "userEnteredFormat": {
                        "backgroundColor": _hex_to_color("#0f172a"),
                        "textFormat": {
                            "bold": True,
                            "foregroundColor": _hex_to_color("#ffffff"),
                        },
                    }
                },
                "fields": "userEnteredFormat(backgroundColor,textFormat)",
            }
        })

        # Date formatting: MMM d, yyyy
        if tab_name == assumptions_tab:
            # As-Of Date (column B) — use row map for robustness
            as_of_row_0 = _assumptions_row_map()["as_of_date"] - 1
            requests.append({
                "repeatCell": {
                    "range": {
                        "sheetId": sheet_id,
                        "startRowIndex": as_of_row_0,
                        "endRowIndex": as_of_row_0 + 1,
                        "startColumnIndex": 1,
                        "endColumnIndex": 2,
                    },
                    "cell": {
                        "userEnteredFormat": {
                            "numberFormat": {
                                "type": "DATE",
                                "pattern": "MMM d, yyyy"
                            }
                        }
                    },
                    "fields": "userEnteredFormat.numberFormat",
                }
            })

    if requests:
        service.spreadsheets().batchUpdate(
            spreadsheetId=spreadsheet_id,
            body={"requests": requests}
        ).execute()


def _validate_sdr(
    service,
    spreadsheet_id: str,
    calc_tab: str,
    inputs: SDRInputs
) -> Dict[str, Any]:
    """Validate the SDR model outputs."""
    errors: List[str] = []

    try:
        # Read calc tab data
        range_str = f"{calc_tab}!A1:G45"
        resp = service.spreadsheets().values().get(
            spreadsheetId=spreadsheet_id,
            range=range_str,
            valueRenderOption="UNFORMATTED_VALUE"
        ).execute()
        values = resp.get("values", [])

        # Check for bottleneck
        for row in values:
            if len(row) >= 2:
                if row[0] == "Bottleneck Status":
                    if row[1] == "BOTTLENECK":
                        errors.append("AE bottleneck detected: SDR output exceeds AE capacity")

        # Check for negative ROI
        for row in values:
            if len(row) >= 2:
                if row[0] == "Plus 1 SDR: Marginal ROI":
                    try:
                        roi = float(row[1])
                        if roi < 0:
                            errors.append("Negative marginal ROI: Adding SDRs would reduce profit")
                    except (ValueError, TypeError):
                        pass

    except Exception as e:
        errors.append(f"Validation error: {str(e)}")

    return {
        "status": "ok" if not errors else "issues",
        "errors": errors,
    }
