"""Thin MyFatoorah HTTP client.

One master API key per merchant account. Only exposes SendPayment for now.
"""

from __future__ import annotations

import logging
from typing import Any

import requests
from django.conf import settings

from apps.core.myfatoorah_exceptions import (
    MyFatoorahError,
    MyFatoorahNotConfigured,
    MyFatoorahValidationError,
)

logger = logging.getLogger(__name__)


class MyFatoorahClient:
    """Wraps MyFatoorah's V2 endpoints."""

    def __init__(
        self,
        base_url: str | None = None,
        api_key: str | None = None,
        timeout: int | None = None,
    ):
        cfg = getattr(settings, "MYFATOORAH", {}) or {}
        self.base_url = (base_url or cfg.get("BASE_URL", "")).rstrip("/")
        self.api_key = api_key or cfg.get("API_KEY", "")
        self.timeout = timeout or cfg.get("TIMEOUT", 15)

        if not self.base_url:
            raise MyFatoorahNotConfigured("MYFATOORAH.BASE_URL is not set.")
        if not self.api_key:
            raise MyFatoorahNotConfigured("MYFATOORAH.API_KEY is not set.")

    # --------------------------- HTTP plumbing ---------------------------

    def _headers(self) -> dict[str, str]:
        return {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
            "Accept": "application/json",
        }

    def _request(
        self,
        method: str,
        path: str,
        *,
        json: dict | None = None,
    ) -> Any:
        url = f"{self.base_url}{path}"
        try:
            resp = requests.request(
                method,
                url,
                headers=self._headers(),
                json=json,
                timeout=self.timeout,
            )
        except requests.RequestException as exc:
            logger.exception("MyFatoorah request failed: %s %s", method, path)
            raise MyFatoorahError(detail=str(exc)) from exc

        try:
            payload = resp.json()
        except ValueError as exc:
            raise MyFatoorahError(
                detail=f"Non-JSON response ({resp.status_code}): {resp.text[:200]}"
            ) from exc

        if not resp.ok:
            raise MyFatoorahError(detail=f"HTTP {resp.status_code}: {payload}")

        if isinstance(payload, dict) and payload.get("IsSuccess") is False:
            errors = (
                payload.get("ValidationErrors")
                or payload.get("FieldsErrors")
                or []
            )
            raise MyFatoorahValidationError(
                detail={
                    "message": payload.get("Message", "Validation error"),
                    "errors": errors,
                }
            )

        if isinstance(payload, dict) and "Data" in payload:
            return payload["Data"]
        return payload

    # --------------------------- Payments ---------------------------

    def send_payment(self, payload: dict) -> dict:
        """POST /v2/SendPayment — create a payment link."""
        return self._request("POST", "/v2/SendPayment", json=payload)


def get_client() -> MyFatoorahClient:
    """Factory used by views. Override in tests via dependency injection."""
    return MyFatoorahClient()
