{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "g3-md-intro",
   "metadata": {},
   "source": [
    "# 03 \u2014 Business Case\n",
    "\n",
    "Combine the benefits and costs into the consolidated TEI summary,\n",
    "render the cash-flow exhibit, run scenario analysis, **and price the\n",
    "Genesys AI Experience tokens line that the published study omits**.\n",
    "This notebook should reproduce the headline numbers from the PDF\n",
    "Financial Summary:\n",
    "\n",
    "* **NPV \\$10.78M \u2022 ROI 266% \u2022 Payback \u2248 4 months**\n",
    "\n",
    "It then exposes a sensitivity sweep for the AI-tokens annual cost so\n",
    "you can see exactly what an honest deal looks like before sending it\n",
    "to a client."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "03-bootstrap",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys, pathlib                       # path shim: works on a fresh kernel\n",
    "for _p in [pathlib.Path.cwd(), *pathlib.Path.cwd().parents]:\n",
    "    if (_p / \"pyproject.toml\").exists():\n",
    "        sys.path.insert(0, str(_p)); break\n",
    "\n",
    "from core.bootstrap import init\n",
    "\n",
    "pal = init(study=\"202512_GenesysCX\")\n",
    "client, seed, config = pal.client, pal.seed_data, pal.config\n",
    "\n",
    "STUDY = pal.root / 'studies' / '202512_GenesysCX'\n",
    "ROOT  = pal.root\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-imports",
   "metadata": {},
   "outputs": [],
   "source": [
    "from core.export.report_data import _compute_summary\n",
    "from core.notebook_helpers import charts, display, tables"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g3-md-summary",
   "metadata": {},
   "source": [
    "## Local summary (no Athena round-trip)\n",
    "\n",
    "Compute the moderate-case TEI summary directly from `seed_data` so the\n",
    "notebook produces results even before the Athena tool is provisioned.\n",
    "Headline numbers should match the published study."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-summary",
   "metadata": {},
   "outputs": [],
   "source": [
    "summary = _compute_summary(\n",
    "    seed.BENEFITS,\n",
    "    seed.COSTS,\n",
    "    config.DISCOUNT_RATE,\n",
    "    config.ANALYSIS_YEARS,\n",
    ")\n",
    "# `_compute_summary` returns roi_pct; expose it as `roi` for kpi_cards.\n",
    "summary['roi'] = summary.get('roi_pct')\n",
    "display.kpi_cards(summary, title='Forrester composite \u2014 moderate case')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-cashflow-table",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_cash = tables.cashflow_table(summary)\n",
    "df_cash.style.format({c: '${:,.0f}' for c in df_cash.columns if c != 'Year'})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g3-md-cashflow",
   "metadata": {},
   "source": [
    "## Cash flow chart\n",
    "\n",
    "Mirrors the Forrester *Cash Flow Chart* exhibit: stacked benefits/costs\n",
    "by year + cumulative-net line. Payback hits inside Year 1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-cashflow-chart",
   "metadata": {},
   "outputs": [],
   "source": [
    "charts.cashflow_chart(\n",
    "    summary['yearly_breakdown'],\n",
    "    initial_cost=summary.get('initial_costs', 0),\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g3-md-waterfall",
   "metadata": {},
   "source": [
    "## Waterfall: Benefits PV \u2192 Costs PV \u2192 NPV"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-waterfall",
   "metadata": {},
   "outputs": [],
   "source": [
    "charts.waterfall([\n",
    "    ('Benefits PV', summary['total_benefits_pv']),\n",
    "    ('Costs PV', -summary['total_costs_pv']),\n",
    "    ('NPV', summary['npv']),\n",
    "]).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g3-md-scenarios",
   "metadata": {},
   "source": [
    "## Scenario analysis\n",
    "\n",
    "Apply the default Palladium multipliers (see `core.calculations.SCENARIOS`):\n",
    "\n",
    "* **Conservative** \u2014 lower adoption, higher risk on benefits / lower on costs\n",
    "* **Moderate** \u2014 base case (= the published Forrester study)\n",
    "* **Aggressive** \u2014 full adoption, lower risk on benefits / higher on costs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-scenarios",
   "metadata": {},
   "outputs": [],
   "source": [
    "from core.calculations import apply_scenario\n",
    "import pandas as pd\n",
    "\n",
    "scenario_summaries = {}\n",
    "for name in ('conservative', 'moderate', 'aggressive'):\n",
    "    sb = apply_scenario(seed.BENEFITS, name, table='benefits')\n",
    "    sc = apply_scenario(seed.COSTS, name, table='costs')\n",
    "    scenario_summaries[name] = _compute_summary(sb, sc, config.DISCOUNT_RATE, config.ANALYSIS_YEARS)\n",
    "\n",
    "scen_df = pd.DataFrame([\n",
    "    {\n",
    "        'Scenario': k,\n",
    "        'Benefits PV': v['total_benefits_pv'],\n",
    "        'Costs PV':   v['total_costs_pv'],\n",
    "        'NPV':        v['npv'],\n",
    "        'ROI %':      v['roi_pct'],\n",
    "        'Payback (mo)': round(v['payback_months'], 1) if v['payback_months'] is not None else None,\n",
    "    }\n",
    "    for k, v in scenario_summaries.items()\n",
    "])\n",
    "scen_df.style.format({\n",
    "    'Benefits PV': '${:,.0f}', 'Costs PV': '${:,.0f}', 'NPV': '${:,.0f}', 'ROI %': '{:,.0f}%'\n",
    "})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-scenario-chart",
   "metadata": {},
   "outputs": [],
   "source": [
    "charts.scenario_comparison(scenario_summaries).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g3-md-tokens-intro",
   "metadata": {},
   "source": [
    "## Genesys AI Experience tokens \u2014 annual cost\n",
    "\n",
    "Token pricing is tiered, capability-dependent, and deal-specific \u2014\n",
    "Athena stores a single annual cost value per line, and so does the\n",
    "seed. Enter the negotiated annual cost from the Genesys quote here.\n",
    "Quote details (volume, unit price, tier) go into the field notes for\n",
    "the audit trail.\n",
    "\n",
    "For sizing context, the study's own drivers imply roughly **1,040,000**\n",
    "self-service interactions/yr and **3,120,000** agent-assisted\n",
    "interactions/yr would draw tokens \u2014 bring the actual figure from the\n",
    "quote, not a derivation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-token-input",
   "metadata": {},
   "outputs": [],
   "source": [
    "# \u2500\u2500 Deal inputs \u2500\u2500\n",
    "AI_TOKEN_ANNUAL_COST = 0.0   # $/yr from the Genesys quote \u2014 0 reproduces the published study\n",
    "AI_TOKEN_QUOTE_NOTE  = \"\"    # e.g. \"Quote #1234: 4.2M tokens/yr @ $0.05, tier 2 commit\"\n",
    "\n",
    "print(f'AI token line: ${AI_TOKEN_ANNUAL_COST:,.0f}/yr')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g3-md-sensitivity",
   "metadata": {},
   "source": [
    "### Sensitivity \u2014 what the AI line does to NPV and ROI\n",
    "\n",
    "An annual cost `\u0394` raises Costs PV by `\u0394 \u00d7 2.4869` (the 3-year, 10%\n",
    "annuity factor) and lowers NPV by the same amount. The sweep below\n",
    "shows where the deal stops being attractive \u2014 and quantifies how much\n",
    "of the published 266% ROI was *contingent on Forrester modelling \\$0\n",
    "of token spend*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-sensitivity",
   "metadata": {},
   "outputs": [],
   "source": [
    "ANNUITY = sum(1 / 1.10**n for n in (1, 2, 3))   # 2.4869\n",
    "\n",
    "base_benefits_pv = float(summary['total_benefits_pv'])\n",
    "base_costs_pv = float(summary['total_costs_pv'])\n",
    "\n",
    "sweep = [0, 100_000, 250_000, 500_000, 750_000, 1_000_000, 1_500_000, 2_000_000]\n",
    "if AI_TOKEN_ANNUAL_COST and AI_TOKEN_ANNUAL_COST not in sweep:\n",
    "    sweep = sorted(sweep + [AI_TOKEN_ANNUAL_COST])\n",
    "\n",
    "rows = []\n",
    "for ai_annual in sweep:\n",
    "    costs_pv = base_costs_pv + ai_annual * ANNUITY\n",
    "    npv_v = base_benefits_pv - costs_pv\n",
    "    roi_pct = (npv_v / costs_pv * 100) if costs_pv else 0\n",
    "    rows.append({\n",
    "        'AI cost/yr': f\"${ai_annual:,.0f}\" + ('  \u2190 your input' if ai_annual == AI_TOKEN_ANNUAL_COST and ai_annual else ''),\n",
    "        'Costs PV':   f'${costs_pv:,.0f}',\n",
    "        'NPV':        f'${npv_v:,.0f}',\n",
    "        'ROI':        f'{roi_pct:,.0f}%',\n",
    "    })\n",
    "\n",
    "pd.DataFrame(rows)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g3-md-tokens-push",
   "metadata": {},
   "source": [
    "### Push the AI-tokens cost to Athena\n",
    "\n",
    "When `AI_TOKEN_ANNUAL_COST` is set and `TOOL_PUBLIC_ID` exists, write\n",
    "the annual cost into the `genesys_ai_tokens` field, with the quote\n",
    "details preserved in the field notes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-tokens-push",
   "metadata": {},
   "outputs": [],
   "source": [
    "PUSH = False   # \u2190 set True once AI_TOKEN_ANNUAL_COST is final\n",
    "\n",
    "if PUSH and config.TOOL_PUBLIC_ID:\n",
    "    from core.tei_client import TEIClient\n",
    "\n",
    "    note = (\n",
    "        f'AI Experience tokens: ${AI_TOKEN_ANNUAL_COST:,.0f}/yr. '\n",
    "        + (f'{AI_TOKEN_QUOTE_NOTE} ' if AI_TOKEN_QUOTE_NOTE else '')\n",
    "        + 'Line absent from the published Forrester study.'\n",
    "    )\n",
    "    client = TEIClient()\n",
    "    client.update_values(config.TOOL_PUBLIC_ID, [{\n",
    "        'field_key': 'genesys_ai_tokens',\n",
    "        'year_values': {'1': round(AI_TOKEN_ANNUAL_COST, 2),\n",
    "                        '2': round(AI_TOKEN_ANNUAL_COST, 2),\n",
    "                        '3': round(AI_TOKEN_ANNUAL_COST, 2)},\n",
    "        'notes': note,\n",
    "    }])\n",
    "    client.calculate(config.TOOL_PUBLIC_ID)\n",
    "    client.print_summary(config.TOOL_PUBLIC_ID)\n",
    "    client.save_version(config.TOOL_PUBLIC_ID, note=f'AI token cost set: {note}')\n",
    "    display.alert('Pushed, recalculated, and versioned.', 'success')\n",
    "else:\n",
    "    display.alert('Dry run \u2014 set <code>PUSH = True</code> and ensure '\n",
    "                  '<code>TOOL_PUBLIC_ID</code> is configured to write to Athena.', 'info')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g3-md-crosscheck",
   "metadata": {},
   "source": [
    "## Cross-check vs Athena (optional)\n",
    "\n",
    "When `TOOL_PUBLIC_ID` is set, ask Athena to recalculate the summary on\n",
    "the server side and confirm it matches our local computation (modulo\n",
    "the documented Year-0 discounting delta \u2014 see `02_costs.ipynb`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "g3-code-crosscheck",
   "metadata": {},
   "outputs": [],
   "source": [
    "if config.TOOL_PUBLIC_ID:\n",
    "    from core.tei_client import TEIClient\n",
    "\n",
    "    client = TEIClient()\n",
    "    client.calculate(config.TOOL_PUBLIC_ID)\n",
    "    server_summary = client.get_summary(config.TOOL_PUBLIC_ID)\n",
    "    display.kpi_cards(server_summary, title='Athena server-side summary')\n",
    "else:\n",
    "    display.alert('Set TOOL_PUBLIC_ID to compare Athena vs local.', 'info')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g3-md-next",
   "metadata": {},
   "source": [
    "Continue with [`04_export.ipynb`](04_export.ipynb) \u2192"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
