"""
Palladium Streamlit app — TEI data entry, calculation, versioning, export.

Run from the project root::

    streamlit run app/main.py

The app picks a TEI tool by ``public_id`` (or creates one from a Report
template) and exposes Benefits, Costs, Summary, and Versions pages. It is
study-agnostic — the field set is loaded dynamically from Athena based on
the linked Report template.
"""

from __future__ import annotations

import sys
from pathlib import Path

# Allow `streamlit run app/main.py` from project root without `pip install -e .`
_ROOT = Path(__file__).resolve().parent.parent
if str(_ROOT) not in sys.path:
    sys.path.insert(0, str(_ROOT))

import streamlit as st

from core.tei_client import AthenaAPIError, TEIClient
from app.utils import icon, inject_icons

st.set_page_config(
    page_title="Palladium — TEI Calculator",
    page_icon="🛡️",
    layout="wide",
)



@st.cache_resource(show_spinner=False)
def get_client() -> TEIClient:
    return TEIClient()


def _safe_call(fn, *args, **kwargs):
    """Run an API call, surfacing errors as Streamlit messages."""
    try:
        return fn(*args, **kwargs)
    except AthenaAPIError as e:
        st.error(f"Athena API error {e.status_code}: {e.detail}")
    except ValueError as e:
        st.error(str(e))
    return None


# CRM lookups, cached briefly so the cascading selects stay snappy.
@st.cache_data(ttl=120, show_spinner=False)
def _crm_clients(_client: TEIClient) -> list[dict]:
    try:
        return _client.list_clients()
    except AthenaAPIError:
        return []


@st.cache_data(ttl=120, show_spinner=False)
def _crm_proposals(_client: TEIClient, client_id: int) -> list[dict]:
    try:
        return _client.proposals_for_client(client_id)
    except AthenaAPIError:
        return []


@st.cache_data(ttl=120, show_spinner=False)
def _crm_engagements(_client: TEIClient, client_name: str) -> list[dict]:
    try:
        return _client.engagements_for_client(client_name)
    except AthenaAPIError:
        return []


def sidebar_tool_picker(client: TEIClient) -> dict | None:
    """Sidebar: pick an existing TEI tool or create one from a report template."""
    st.sidebar.markdown(
        f"{icon('shield-fill')} **Palladium**", unsafe_allow_html=True
    )
    st.sidebar.caption("TEI Calculator")

    tools = _safe_call(client.list_tools) or []
    if tools:
        labels = {
            f"{t.get('name', '(unnamed)')} — {t.get('id', '')[:8]}…": t for t in tools
        }
        choice = st.sidebar.selectbox("TEI Tool", list(labels.keys()))
        tool = labels[choice]
    else:
        st.sidebar.info("No TEI tools yet. Create one below.")
        tool = None

    with st.sidebar.expander("Create new tool"):
        reports = _safe_call(client.list_reports) or []
        if not reports:
            st.write("No report templates available.")
        else:
            report_labels = {f"{r['name']} ({r['vendor']} {r['version']})": r for r in reports}
            r_choice = st.selectbox("Report template", list(report_labels.keys()))

            # A TEI tool must attach to a Proposal OR an Engagement.
            # Cascade: client → proposal/engagement, pulled from the CRM.
            clients = _crm_clients(client)
            if not clients:
                st.warning("No CRM clients found — create one in Athena first.")
                return tool
            client_labels = {c["name"]: c for c in clients}
            c_choice = st.selectbox("Client", list(client_labels.keys()))
            crm_client = client_labels[c_choice]

            attach_kind = st.radio(
                "Attach to", ["Proposal", "Engagement"], horizontal=True
            )
            proposal_id: int | None = None
            engagement_id: int | None = None
            if attach_kind == "Proposal":
                proposals = _crm_proposals(client, crm_client["id"])
                if proposals:
                    p_labels = {
                        f"{p.get('name')} ({p.get('status')})": p for p in proposals
                    }
                    p_choice = st.selectbox("Proposal", list(p_labels.keys()))
                    proposal_id = p_labels[p_choice]["id"]
                else:
                    st.info(
                        f"{crm_client['name']} has no proposals. Create one in "
                        "Athena (or via 00_provision.ipynb) first."
                    )
            else:
                engagements = _crm_engagements(client, crm_client["name"])
                if engagements:
                    e_labels = {
                        f"{e.get('name')} ({e.get('status')})": e for e in engagements
                    }
                    e_choice = st.selectbox("Engagement", list(e_labels.keys()))
                    engagement_id = e_labels[e_choice]["id"]
                else:
                    st.info(f"{crm_client['name']} has no engagements.")

            default_name = f"{crm_client['name']} — {report_labels[r_choice]['name']}"
            new_name = st.text_input("Tool name", default_name)
            if st.button(
                "Create", disabled=proposal_id is None and engagement_id is None
            ):
                report = report_labels[r_choice]
                created = _safe_call(
                    client.create_tool,
                    report_public_id=report["id"],
                    proposal=proposal_id,
                    engagement=engagement_id,
                    name=new_name or None,
                )
                if created:
                    st.success(f"Created tool {created.get('id')}")
                    st.cache_data.clear()
                    st.rerun()

    if tool:
        st.sidebar.divider()
        _opp = tool.get("opportunity") or {}
        _client_name = (_opp.get("client") or {}).get("name")
        if _client_name:
            st.sidebar.markdown(f"**Client**: {_client_name}")
        st.sidebar.markdown(f"**Public ID**: `{tool.get('id')}`")
        st.sidebar.markdown(f"**Status**: {tool.get('status', '?')}")
        st.sidebar.markdown(f"**Version**: {tool.get('current_version', 0)}")
        if st.sidebar.button("Recalculate"):
            _safe_call(client.calculate, tool["id"])
            st.toast("Recalculated.", icon=None)
            st.cache_data.clear()
    return tool


def main() -> None:
    inject_icons()

    st.markdown(
        f"<h1 style='margin-bottom:0'>{icon('shield-fill')} Palladium — TEI Calculator</h1>",
        unsafe_allow_html=True,
    )
    try:
        client = get_client()
    except ValueError as e:
        st.error(str(e))
        st.info("Set ATHENA_BASE_URL and ATHENA_API_KEY in your `.env` file.")
        st.stop()
        return

    tool = sidebar_tool_picker(client)

    if tool is None:
        st.info("Pick or create a TEI tool from the sidebar to begin.")
        return

    # Tab navigation — matches `app/views/*` modules but kept as tabs so all
    # views share the chosen tool/state without re-querying.
    #
    # NOTE: the directory is `app/views/`, NOT `app/pages/`. Streamlit treats a
    # `pages/` directory next to the entrypoint as auto-discovered multipage
    # scripts, which would render blank since these modules only define
    # `render()` and have no top-level output.
    tabs = st.tabs(["Summary", "Benefits", "Costs", "Versions"])

    from app.views import benefits as benefits_page
    from app.views import costs as costs_page
    from app.views import summary as summary_page
    from app.views import versions as versions_page

    with tabs[0]:
        summary_page.render(client, tool)
    with tabs[1]:
        benefits_page.render(client, tool)
    with tabs[2]:
        costs_page.render(client, tool)
    with tabs[3]:
        versions_page.render(client, tool)


if __name__ == "__main__":
    main()
