from __future__ import annotations

import re
from typing import Any, Dict

import httpx
from fastapi import APIRouter, HTTPException, Path, status

_CNPJ_API_TEMPLATE = "https://www.receitaws.com.br/v1/cnpj/{cnpj}"
_CNPJ_SUCCESS_EXAMPLE: Dict[str, Any] = {
    "status": "OK",
    "cnpj": "27865757000102",
    "tipo": "MATRIZ",
    "abertura": "10/05/2010",
    "nome": "SAVE IN MED COMERCIO DE MEDICAMENTOS LTDA",
    "fantasia": "SAVE IN MED",
    "porte": "DEMAIS",
    "natureza_juridica": "206-2 - Sociedade Empresária Limitada",
    "situacao": "ATIVA",
    "capital_social": "50000.00",
    "atividade_principal": [
        {
            "code": "47.71-7-01",
            "text": "Comércio varejista de produtos farmacêuticos, sem manipulação de fórmulas",
        }
    ],
    "atividades_secundarias": [
        {
            "code": "47.89-0-99",
            "text": "Comércio varejista de outros produtos não especificados anteriormente",
        }
    ],
    "qsa": [
        {
            "nome": "MARIA DE SOUZA LIMA",
            "qual": "16-Sócio",
        }
    ],
}

router = APIRouter(
    prefix="/public/cnpj",
    tags=["Público • CNPJ"],
)


def _normalize_cnpj(raw: str) -> str:
    return re.sub(r"\D", "", raw or "")


@router.get(
    "/{cnpj:path}",
    summary="Consulta pública de CNPJ (ReceitaWS)",
    description=(
        "Consulta o serviço público da ReceitaWS para obter informações do CNPJ fornecido."
    ),
    responses={
        status.HTTP_200_OK: {
            "description": "Retorno da ReceitaWS",
            "content": {"application/json": {"example": _CNPJ_SUCCESS_EXAMPLE}},
        },
        status.HTTP_404_NOT_FOUND: {
            "description": "CNPJ não encontrado",
            "content": {"application/json": {"example": {"detail": "CNPJ não encontrado"}}},
        },
        status.HTTP_422_UNPROCESSABLE_ENTITY: {
            "description": "CNPJ inválido",
            "content": {
                "application/json": {
                    "example": {"detail": "CNPJ deve conter 14 dígitos numéricos."}
                }
            },
        },
        status.HTTP_429_TOO_MANY_REQUESTS: {
            "description": "Serviço externo indisponível",
            "content": {
                "application/json": {
                    "example": {"detail": "Serviço externo indisponível"}
                }
            },
        },
        status.HTTP_502_BAD_GATEWAY: {
            "description": "Erro ao acessar serviço externo",
            "content": {
                "application/json": {
                    "example": {"detail": "Serviço externo indisponível"}
                }
            },
        },
    },
)
async def consultar_cnpj(
    cnpj: str = Path(
        ...,
        description="CNPJ a ser consultado. Aceita formatos com ou sem máscara.",
        examples={"mascarado": {"value": "27.865.757/0001-02"}},
    ),
) -> Dict[str, Any]:
    normalized = _normalize_cnpj(cnpj)
    if len(normalized) != 14:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail="CNPJ deve conter 14 dígitos numéricos.",
        )

    url = _CNPJ_API_TEMPLATE.format(cnpj=normalized)
    try:
        async with httpx.AsyncClient(timeout=10.0) as client:
            external_response = await client.get(url, headers={"Accept": "application/json"})
    except httpx.RequestError as exc:  # pragma: no cover - proteção contra falhas de rede reais
        raise HTTPException(
            status_code=status.HTTP_502_BAD_GATEWAY,
            detail="Serviço externo indisponível",
        ) from exc

    status_code = external_response.status_code
    try:
        data = external_response.json()
    except ValueError:
        data = None

    if status_code in {status.HTTP_429_TOO_MANY_REQUESTS} or status_code >= 500:
        message = ""
        if isinstance(data, dict) and isinstance(data.get("message"), str):
            message = f": {data['message']}"
        raise HTTPException(
            status_code=status_code,
            detail=f"Serviço externo indisponível{message}",
        )

    if status_code == status.HTTP_404_NOT_FOUND:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="CNPJ não encontrado")

    if isinstance(data, dict) and data.get("status") == "ERROR":
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="CNPJ não encontrado")

    if status_code != status.HTTP_200_OK or not isinstance(data, dict):
        detail_message = "Erro ao consultar CNPJ."
        if isinstance(data, dict) and isinstance(data.get("message"), str):
            detail_message = data["message"]
        raise HTTPException(status_code=status_code, detail=detail_message)

    return data
