"""Client HTTP singleton para comunicação com Google Chat Webhooks."""

import httpx
import os
import logging
from urllib.parse import urlencode, urlparse, parse_qs, urlunparse
from uuid import uuid4

from pack_mcp_google_chat_notification.errors import sanitize_url

logger = logging.getLogger(__name__)

VALID_WEBHOOK_PREFIX = "https://chat.googleapis.com/"


class GoogleChatClient:
    """Client HTTP singleton para comunicação com Google Chat Webhooks."""

    _instance: "GoogleChatClient | None" = None
    DEFAULT_TIMEOUT = 10.0

    def __init__(self, default_webhook_url: str | None = None):
        self._default_webhook_url = default_webhook_url
        self._http_client = httpx.AsyncClient(timeout=self.DEFAULT_TIMEOUT)

    @classmethod
    def get_instance(cls) -> "GoogleChatClient":
        if cls._instance is None:
            cls._instance = cls(
                default_webhook_url=os.environ.get("GOOGLE_CHAT_WEBHOOK_URL")
            )
        return cls._instance

    @classmethod
    def reset(cls) -> None:
        """Reset singleton (para testes)."""
        cls._instance = None

    @property
    def default_webhook_url(self) -> str | None:
        return self._default_webhook_url

    def resolve_webhook_url(self, webhook_url: str | None) -> str:
        """Resolve webhook URL: parâmetro > env var. Levanta ValueError se nenhum disponível."""
        url = webhook_url or self._default_webhook_url
        if not url:
            raise ValueError(
                "Nenhum webhook configurado. Forneça webhook_url ou defina GOOGLE_CHAT_WEBHOOK_URL"
            )
        return url

    def validate_webhook_url(self, url: str) -> None:
        """Valida que a URL começa com https://chat.googleapis.com/. Levanta ValueError se inválida."""
        if not url.startswith(VALID_WEBHOOK_PREFIX):
            raise ValueError(
                "URL do webhook inválida. Deve começar com https://chat.googleapis.com/"
            )

    def _build_url(self, webhook_url: str, params: dict | None = None) -> str:
        """Constrói URL final com query params opcionais (ex: threadKey, messageReplyOption).

        Preserva parâmetros existentes na URL e adiciona os novos.
        """
        if not params:
            return webhook_url

        parsed = urlparse(webhook_url)
        existing_params = parse_qs(parsed.query, keep_blank_values=True)
        # Flatten existing params (parse_qs returns lists)
        merged: dict[str, str] = {}
        for k, v in existing_params.items():
            merged[k] = v[0] if len(v) == 1 else v
        merged.update(params)
        new_query = urlencode(merged, doseq=True)
        return urlunparse(parsed._replace(query=new_query))

    async def post(self, webhook_url: str, payload: dict, params: dict | None = None) -> dict:
        """Envia POST para o webhook. Retorna response body ou levanta exceção.

        Args:
            webhook_url: URL do webhook do Google Chat.
            payload: Corpo da requisição (dict serializado como JSON).
            params: Query params opcionais para adicionar à URL (ex: threadKey).

        Returns:
            dict com o body da resposta em caso de sucesso (HTTP 200).

        Raises:
            ValueError: Em caso de erro HTTP ou timeout.
        """
        url = self._build_url(webhook_url, params)
        sanitized = sanitize_url(url)
        logger.info("Enviando POST para %s", sanitized)

        try:
            response = await self._http_client.post(
                url,
                json=payload,
                headers={"Content-Type": "application/json"},
            )
        except httpx.TimeoutException:
            raise ValueError("Timeout de conexão ao enviar mensagem para o Google Chat")

        if response.status_code == 200:
            return response.json()

        raise ValueError(f"Erro HTTP {response.status_code}: {response.text}")



def build_text_payload(text: str) -> dict:
    """Constrói payload de texto simples."""
    return {"text": text}


def build_card_payload(title: str, sections: list[dict], subtitle: str | None = None) -> dict:
    """Constrói payload Card V2."""
    header: dict = {"title": title}
    if subtitle is not None:
        header["subtitle"] = subtitle

    return {
        "cardsV2": [
            {
                "cardId": str(uuid4()),
                "card": {
                    "header": header,
                    "sections": sections,
                },
            }
        ]
    }


def parse_card_payload(payload: dict) -> tuple[str, list[dict], str | None]:
    """Extrai title, sections e subtitle de um payload Card V2."""
    card_wrapper = payload["cardsV2"][0]
    card = card_wrapper["card"]
    header = card["header"]

    title = header["title"]
    sections = card["sections"]
    subtitle = header.get("subtitle")

    return title, sections, subtitle


def get_client() -> GoogleChatClient:
    """Atalho para obter a instância singleton."""
    return GoogleChatClient.get_instance()
