from __future__ import annotations

import logging

from app.ws_gateway.session_bootstrap import build_bridge_session_bootstrap
from app.ws_gateway.session_start import StartSessionContext


def _build_start_ctx(**data_overrides: str) -> StartSessionContext:
    data = {
        "agent": "oferta",
        "ani": "5511888888888",
        "gsm": "5511999999999",
        "session_id": "550e8400-e29b-41d4-a716-446655440100",
        "routerCallKeyDay": "20260409",
        "routerCallKey": "RCK-001",
        "callIdGed": "GED-1234567890",
        **data_overrides,
    }
    payload = {
        "type": "start",
        "data": data,
        "callConfig": {
            "tts": {"provider": "azure"},
        },
    }
    return StartSessionContext(
        payload=payload,
        data=data,
        agent_data=dict(data.get("agentData") or {}),
        audio_format={},
        call_config=payload["callConfig"],
        session_data={"gsm": data.get("gsm", ""), "msisdn": data.get("gsm", ""), **data},
        intro="intro",
        nudge="nudge",
    )


def test_build_bridge_session_bootstrap_uses_protocol_from_data_and_builds_dispatch_metadata(
    monkeypatch,
) -> None:
    logger = logging.getLogger("test.session_bootstrap")
    monkeypatch.setenv("CALL_TIMELINE_DIR", "/tmp/timeline-bootstrap")
    monkeypatch.setenv("CALL_TIMELINE_ENABLED", "0")

    data = {
        "agent": "conta",
        "ani": "5511888888888",
        "gsm": "5511888888888",
        "session_id": "550e8400-e29b-41d4-a716-446655440101",
        "routerCallKeyDay": "20260409",
        "routerCallKey": "RCK-321",
        "callIdGed": "GED-321",
        "protocolo": "PRT-321",
        "agentData": {
            "idFatura": "fat-999",
        },
    }
    start_ctx = StartSessionContext(
        payload={
            "type": "start",
            "data": data,
            "callConfig": {
                "tts": {"provider": "azure"},
            },
        },
        data=data,
        agent_data={"idFatura": "fat-999"},
        audio_format={},
        call_config={"tts": {"provider": "azure"}},
        session_data={"gsm": "5511888888888", "msisdn": "5511888888888", **data},
        intro="intro",
        nudge="nudge",
    )

    uuids = iter(
        [
            type("U", (), {"hex": "room123456789"})(),
            type("U", (), {"hex": "ident12345678"})(),
        ]
    )
    token_calls: list[tuple[str, str]] = []

    bootstrap = build_bridge_session_bootstrap(
        start_ctx=start_ctx,
        app_env="dev",
        livekit_room="custom-room",
        default_protocol="fallback-proto",
        token_factory=lambda identity, room_name: token_calls.append((identity, room_name)) or "jwt-token",
        logger=logger,
        now_fn=lambda: 1234567890,
        uuid_factory=lambda: next(uuids),
    )

    assert bootstrap.call_id_ged == "GED-321"
    assert bootstrap.room_name == "custom-room-room1234"
    assert bootstrap.identity == "ws-bridge-dev-ident123"
    assert bootstrap.token == "jwt-token"
    assert bootstrap.protocol == "PRT-321"
    assert bootstrap.phone_number == "5511888888888"
    assert bootstrap.remote_agent_context["agent"] == "conta"
    assert bootstrap.remote_agent_context["ID_FATURA"] == "fat-999"
    assert bootstrap.remote_agent_context["callIdGed"] == "GED-321"
    assert bootstrap.call_config["tts"]["provider"] == "azure"
    assert bootstrap.dispatch_metadata["bridge_identity"] == "ws-bridge-dev-ident123"
    assert bootstrap.dispatch_metadata["protocol"] == "PRT-321"
    assert bootstrap.dispatch_metadata["call_id_ged"] == "GED-321"
    assert bootstrap.dispatch_metadata["agent_starts_conversation"] is True
    assert bootstrap.dispatch_metadata["remote_agent"]["ID_FATURA"] == "fat-999"
    assert bootstrap.dispatch_metadata["timeline_id"] == "custom-room-room1234"
    assert bootstrap.dispatch_metadata["session_id"] == "550e8400-e29b-41d4-a716-446655440101"
    assert token_calls == [("ws-bridge-dev-ident123", "custom-room-room1234")]


def test_build_bridge_session_bootstrap_falls_back_to_router_call_key_when_protocol_is_missing(
    monkeypatch,
) -> None:
    logger = logging.getLogger("test.session_bootstrap")
    monkeypatch.setenv("CALL_TIMELINE_DIR", "/tmp/timeline-bootstrap")
    monkeypatch.setenv("CALL_TIMELINE_ENABLED", "0")

    start_ctx = _build_start_ctx()

    bootstrap = build_bridge_session_bootstrap(
        start_ctx=start_ctx,
        app_env="dev",
        livekit_room="custom-room",
        default_protocol="fallback-proto",
        token_factory=lambda *_args: "jwt-token",
        logger=logger,
        now_fn=lambda: 1234567890,
        uuid_factory=lambda: type("U", (), {"hex": "room123456789"})(),
    )

    assert bootstrap.protocol == "RCK-001"
    assert bootstrap.dispatch_metadata["protocol"] == "RCK-001"


def test_build_bridge_session_bootstrap_falls_back_to_generated_protocol_and_phone(monkeypatch) -> None:
    logger = logging.getLogger("test.session_bootstrap")
    monkeypatch.setenv("CALL_TIMELINE_DIR", "/tmp/timeline-bootstrap")
    monkeypatch.setenv("CALL_TIMELINE_ENABLED", "0")

    start_ctx = _build_start_ctx(routerCallKey="", gsm="")
    start_ctx = StartSessionContext(
        payload=start_ctx.payload,
        data=start_ctx.data,
        agent_data=start_ctx.agent_data,
        audio_format=start_ctx.audio_format,
        call_config=start_ctx.call_config,
        session_data={**start_ctx.session_data, "phone": "5511777777777"},
        intro=start_ctx.intro,
        nudge=start_ctx.nudge,
    )
    uuids = iter(
        [
            type("U", (), {"hex": "roomabcdef1234"})(),
            type("U", (), {"hex": "identfedcba98"})(),
        ]
    )

    bootstrap = build_bridge_session_bootstrap(
        start_ctx=start_ctx,
        app_env="qa",
        livekit_room="",
        default_protocol="",
        token_factory=lambda *_args: "jwt-token",
        logger=logger,
        now_fn=lambda: 1712345678,
        uuid_factory=lambda: next(uuids),
    )

    assert bootstrap.room_name == "qa-room-roomabcd"
    assert bootstrap.identity == "ws-bridge-qa-identfed"
    assert bootstrap.protocol == "WS-GED-1234567890-1712345678"
    assert bootstrap.phone_number == "5511777777777"
    assert bootstrap.dispatch_metadata["session_id"] == "550e8400-e29b-41d4-a716-446655440100"
    assert bootstrap.dispatch_metadata["agent_starts_conversation"] is True
    assert bootstrap.dispatch_metadata["session_data"]["phone"] == "5511777777777"


def test_build_bridge_session_bootstrap_uses_explicit_session_id_without_protocol_fallback(monkeypatch) -> None:
    logger = logging.getLogger("test.session_bootstrap.session_id")
    monkeypatch.setenv("CALL_TIMELINE_DIR", "/tmp/timeline-bootstrap")
    monkeypatch.setenv("CALL_TIMELINE_ENABLED", "0")

    start_ctx = _build_start_ctx(protocolo="PRT-001", session_id="sess-001")

    bootstrap = build_bridge_session_bootstrap(
        start_ctx=start_ctx,
        app_env="dev",
        livekit_room="custom-room",
        default_protocol="fallback-proto",
        token_factory=lambda *_args: "jwt-token",
        logger=logger,
        now_fn=lambda: 1234567890,
        uuid_factory=lambda: type("U", (), {"hex": "room123456789"})(),
    )

    assert bootstrap.protocol == "PRT-001"
    assert bootstrap.dispatch_metadata["session_id"] == "sess-001"
