from __future__ import annotations

import os
from typing import Any, Dict

from app.livekit.adapters.agent_backend import AgentBackend


def _env_first(*names: str) -> str:
    for name in names:
        value = (os.getenv(name, "") or "").strip()
        if value:
            return value
    return ""


def _normalize_agent_name(value: Any) -> str:
    raw = str(value or "").strip().lower()
    aliases = {
        "conta": "conta",
        "contas": "conta",
        "ofert": "oferta",
        "oferta": "oferta",
        "ofertas": "oferta",
        "cobra": "cobranca",
        "cobranca": "cobranca",
        "cobrança": "cobranca",
        "cobrancas": "cobranca",
        "cobranças": "cobranca",
    }
    return aliases.get(raw, raw)


def _current_agent_name(remote_agent_context: Dict[str, Any] | None) -> str:
    context = remote_agent_context or {}
    return _normalize_agent_name(
        context.get("agent")
        or context.get("Agent")
        or context.get("agente")
        or ""
    )


def build_agent_backend(
    *,
    intro: str,
    backend_name: str | None = None,
    remote_agent_context: Dict[str, Any] | None = None,
    timeline: Any | None = None,
    streaming: bool = False,
) -> AgentBackend:
    requested_backend = (backend_name or os.getenv("AGENT_BACKEND", "remote_ws") or "remote_ws").strip().lower()
    backend = requested_backend
    use_fake_remote = backend in {"remote_ws_fake", "fake_remote_ws", "ws_fake"}

    if use_fake_remote:
        from app.livekit.adapters.fake_remote_ws_adapter import FakeRemoteWSAdapter

        fake_delay_ms = (remote_agent_context or {}).get("_fake_agent_delay_ms")
        fake_responses = (remote_agent_context or {}).get("_fake_agent_responses")
        return FakeRemoteWSAdapter(
            intro=intro,
            backend_label="remote_ws_fake",
            request_context=remote_agent_context or {},
            timeline=timeline,
            default_stage=(os.getenv("REMOTE_AGENT_WS_DEFAULT_STAGE", "PRESENTATION") or "PRESENTATION").strip(),
            delay_ms=fake_delay_ms,
            responses=fake_responses,
        )

    if backend == "langgraph":
        raise RuntimeError("AGENT_BACKEND=langgraph is no longer supported in the websocket runtime")

    if backend in {"remote_ws", "ws", "websocket"}:
        from app.livekit.adapters.remote_agent_ws_adapter import RemoteAgentWSAdapter

        url = _env_first("REMOTE_AGENT_WS_URL")
        if not url:
            raise RuntimeError("REMOTE_AGENT_WS_URL must be set when AGENT_BACKEND=remote_ws")

        return RemoteAgentWSAdapter(
            intro=intro,
            url=url,
            backend_label="remote_ws_fake" if use_fake_remote else requested_backend,
            url_by_agent={},
            request_context=remote_agent_context or {},
            timeline=timeline,
            streaming=streaming,
            default_stage=(os.getenv("REMOTE_AGENT_WS_DEFAULT_STAGE", "PRESENTATION") or "PRESENTATION").strip(),
            open_timeout_s=float(os.getenv("REMOTE_AGENT_WS_OPEN_TIMEOUT_S", "10")),
            read_timeout_s=float(os.getenv("REMOTE_AGENT_WS_READ_TIMEOUT_S", "45")),
            write_timeout_s=float(os.getenv("REMOTE_AGENT_WS_WRITE_TIMEOUT_S", "10")),
            close_timeout_s=float(os.getenv("REMOTE_AGENT_WS_CLOSE_TIMEOUT_S", "10")),
            max_message_bytes=int(os.getenv("REMOTE_AGENT_WS_MAX_MESSAGE_BYTES", str(1024 * 1024))),
        )

    if backend in {"remote_sse", "sse"}:
        from app.livekit.adapters.remote_agent_sse_adapter import RemoteAgentSSEAdapter

        url_by_agent = {
            "conta": _env_first("REMOTE_AGENT_SSE_URL_CONTA", "REMOTE_AGENT_SSE_URL_CONTAS"),
            "oferta": _env_first("REMOTE_AGENT_SSE_URL_OFERTA", "REMOTE_AGENT_SSE_URL_OFERTAS"),
            "cobranca": _env_first(
                "REMOTE_AGENT_SSE_URL_COBRANCA",
                "REMOTE_AGENT_SSE_URL_COBRANCAS",
                "REMOTE_AGENT_SSE_URL_COBRA",
            ),
        }
        current_agent = _current_agent_name(remote_agent_context)
        url = url_by_agent.get(current_agent, "")
        if not url:
            expected_env = {
                "conta": "REMOTE_AGENT_SSE_URL_CONTA",
                "oferta": "REMOTE_AGENT_SSE_URL_OFERTA",
                "cobranca": "REMOTE_AGENT_SSE_URL_COBRANCA",
            }.get(current_agent, "REMOTE_AGENT_SSE_URL_<AGENT>")
            raise RuntimeError(
                f"{expected_env} must be set when AGENT_BACKEND=remote_sse"
            )

        return RemoteAgentSSEAdapter(
            intro=intro,
            url=url,
            backend_label=requested_backend,
            url_by_agent=url_by_agent,
            request_context=remote_agent_context or {},
            timeline=timeline,
            streaming=streaming,
            default_stage=(os.getenv("REMOTE_AGENT_SSE_DEFAULT_STAGE", "PRESENTATION") or "PRESENTATION").strip(),
            connect_timeout_s=float(os.getenv("REMOTE_AGENT_SSE_CONNECT_TIMEOUT_S", "10")),
            read_timeout_s=float(os.getenv("REMOTE_AGENT_SSE_READ_TIMEOUT_S", "45")),
            write_timeout_s=float(os.getenv("REMOTE_AGENT_SSE_WRITE_TIMEOUT_S", "10")),
        )

    raise RuntimeError(f"Unsupported AGENT_BACKEND={backend!r}")
