"""Engagement data — SHAPE pins only.

The master ships placeholders; an engagement copy fills them in. So these
tests pin the *shape* of the cell and never its emptiness — asserting that
``client`` is blank would fail the moment the copy is used for real, which
is precisely backwards.
"""

from __future__ import annotations

from typing import Any

import nbformat

from tests.conftest import NOTEBOOK

IDENTITY_KEYS = {"client", "prepared_date", "prepared_by"}

VOLUME_KEYS = {
    "voice_inbound_monthly",
    "voice_outbound_monthly",
    "digital_sessions_monthly",
    "email_monthly",
    "messaging_monthly",
    "social_posts_monthly",
    "social_responses_monthly",
    "translations_monthly",
    "evaluations_monthly",
    "ai_actions_monthly",
    "routed_interactions_monthly",
}

COMMERCIAL_KEYS = {
    "agent_users",
    "licence_model",
    "currency",
    "contracted_rate_per_token",
    "concession_pct",
}

TTS_KEYS = {"tts_chars_per_call", "tts_voice_tier"}


def test_engagement_shape(engagement: dict[str, Any]) -> None:
    assert set(engagement) == (
        IDENTITY_KEYS | VOLUME_KEYS | COMMERCIAL_KEYS | TTS_KEYS
    )


def test_identity_fields_are_strings(engagement: dict[str, Any]) -> None:
    """Blank in the master, filled in the copy — either way, strings."""
    for key in IDENTITY_KEYS:
        assert isinstance(engagement[key], str)


def test_volumes_are_non_negative_numbers(engagement: dict[str, Any]) -> None:
    for key in VOLUME_KEYS:
        value = engagement[key]
        assert isinstance(value, (int, float)) and not isinstance(value, bool)
        assert value >= 0, f"{key} must not be negative"


def test_commercial_terms_are_well_formed(engagement: dict[str, Any]) -> None:
    assert isinstance(engagement["agent_users"], int)
    assert engagement["agent_users"] >= 0
    assert engagement["licence_model"] in ("named", "concurrent")
    assert isinstance(engagement["currency"], str) and engagement["currency"]
    assert 0.0 <= float(engagement["concession_pct"]) < 1.0
    contracted = engagement["contracted_rate_per_token"]
    assert contracted is None or float(contracted) >= 0


def test_currency_is_one_the_rate_card_publishes(engagement: dict[str, Any]) -> None:
    from genesyscalc.ratecard import LIST_PRICE_BY_CURRENCY

    assert engagement["currency"] in LIST_PRICE_BY_CURRENCY


def test_tts_settings(engagement: dict[str, Any]) -> None:
    from genesyscalc.tts import TTS_PRICE_PER_MILLION_CHARS

    assert isinstance(engagement["tts_chars_per_call"], int)
    assert engagement["tts_chars_per_call"] >= 0
    assert engagement["tts_voice_tier"] in TTS_PRICE_PER_MILLION_CHARS


def test_master_carries_no_client_identity(engagement: dict[str, Any]) -> None:
    """The one emptiness check that IS correct: masters stay client-clean.

    This guards the master in THIS repo. An engagement copy lives outside
    Palladium, so it never runs this suite — filling the cell there does not
    break anything (CLAUDE.md § Confidentiality).
    """
    assert engagement["client"] == "", (
        "a client name in the master means the copy-out step was skipped — "
        "copy the directory out of Palladium before entering client data"
    )


def test_engagement_cell_sits_above_the_widget_cell() -> None:
    """Client data must not re-run on a sidebar change (Mercury re-runs only
    cells below a changed widget)."""
    nb = nbformat.read(NOTEBOOK, as_version=4)
    eng = [
        i
        for i, c in enumerate(nb.cells)
        if "engagement-data" in c.metadata.get("tags", [])
    ]
    widgets = [
        i
        for i, c in enumerate(nb.cells)
        if c.cell_type == "code" and "mr.Select(" in c.source
    ]
    assert len(eng) == 1 and widgets
    assert eng[0] < min(widgets)
