"""
Async HTTP helper for Payrix REST calls using httpx.AsyncClient.

Provides consistent error handling and structured logging.
"""
from __future__ import annotations

import logging
from typing import Any, Dict, Optional

import httpx

from src.core.payrix.config import get_payrix_config, get_auth_headers
from src.core.config import settings
from src.core.exceptions import PayrixApiError

logger = logging.getLogger("payrix")


def _extract_request_id(resp: httpx.Response) -> Optional[str]:
    # Common header names we might see
    for name in (
        "x-request-id",
        "X-Request-Id",
        "x-correlation-id",
        "X-Correlation-Id",
        "request-id",
    ):
        val = resp.headers.get(name)
        if val:
            return val
    # Sometimes present in body
    try:
        body = resp.json()
        for key in ("requestId", "request_id", "correlationId", "correlation_id"):
            if key in body and isinstance(body[key], str):
                return body[key]
    except Exception:
        pass
    return None


async def payrix_request(
    operation: str,
    method: str,
    path: str,
    *,
    json: Any | None = None,
    params: Dict[str, Any] | None = None,
    headers: Dict[str, str] | None = None,
    merchant_id: str | None = None,
    customer_id: str | None = None,
    token: str | None = None,
    transaction_id: str | None = None,
    timeout: float = 30.0,
) -> httpx.Response:
    """
    Perform a Payrix HTTP request with consistent auth, logging, and error mapping.

    Args:
        operation: Logical operation name for logging (e.g., "create_customer")
        method: HTTP method (GET, POST, etc.)
        path: Endpoint path relative to base URL (e.g., "/v2/customers")
        json: Optional JSON body
        params: Optional query params
        headers: Optional additional headers merged with auth headers
        merchant_id, customer_id, token, transaction_id: Logging context fields
        timeout: Request timeout in seconds

    Returns:
        httpx.Response on success (2xx).

    Raises:
        PayrixApiError on non-2xx responses.
    """
    cfg = get_payrix_config()
    base_headers = get_auth_headers()
    merged_headers = {**base_headers, **(headers or {})}

    print(f"==============cfg============ {cfg}")

    # If this is a GET without a body, avoid sending Content-Type
    if method.upper() == "GET":
        merged_headers.pop("Content-Type", None)
    print(f"==============merged_headers============ {merged_headers}")

    # Ensure path formatting
    rel_path = path if path.startswith("/") else f"/{path}"

    # Log request start (do not log secrets)
    # logger.info(
    #     "provider=payrix op=%s method=%s url=%s merchant_id=%s customer_id=%s token=%s transaction_id=%s",
    #     operation,
    #     method,
    #     f"{cfg.base_url}{rel_path}",
    #     merchant_id or "",
    #     customer_id or "",
    #     ("***" if token else ""),
    #     transaction_id or "",
    # )
    async with httpx.AsyncClient(base_url=cfg.base_url, timeout=timeout, headers=merged_headers) as client:
        resp = await client.request(method.upper(), rel_path, json=json, params=params)

    # Success
    if 200 <= resp.status_code < 300:
        # logger.info(
        #     "provider=payrix op=%s status=%s request_id=%s merchant_id=%s customer_id=%s transaction_id=%s",
        #     operation,
        #     resp.status_code,
        #     _extract_request_id(resp) or "",
        #     merchant_id or "",
        #     customer_id or "",
        #     transaction_id or "",
        # )
        return resp

    # Error mapping
    request_id = _extract_request_id(resp)
    try:
        body: Any = resp.json()
    except Exception:
        body = resp.text

    # logger.error(
    #     "provider=payrix op=%s status=%s request_id=%s merchant_id=%s customer_id=%s transaction_id=%s",
    #     operation,
    #     resp.status_code,
    #     request_id or "",
    #     merchant_id or "",
    #     customer_id or "",
    #     transaction_id or "",
    # )
    raise PayrixApiError(status_code=resp.status_code, payrix_error_body=body, request_id=request_id)
