"""PixorAds bot CPC helper for aiogram 3. Requires httpx. BotFather token stays here.

Call only AFTER delivering a useful result, in a private user chat. Use a stable
event_id (e.g. update_id) and the actual Telegram sender's ID, never an invented ID.
No automatic retry of Telegram sends: an unknown outcome must not send twice.
"""

import re
from typing import Any, cast
from urllib.parse import urlsplit
from uuid import UUID

import httpx
from aiogram import Bot
from aiogram.exceptions import TelegramAPIError, TelegramBadRequest, TelegramForbiddenError


def _object(value: object) -> dict[str, Any]:
    if not isinstance(value, dict):
        raise TypeError("Invalid ad response")
    return cast(dict[str, Any], value)


class PixorAdsBot:
    def __init__(self, api_key: str, base_url: str = "https://pixora-ads.com") -> None:
        parsed = urlsplit(base_url)
        if (
            not api_key.strip()
            or parsed.scheme != "https"
            or not parsed.hostname
            or parsed.username
            or parsed.password
            or parsed.query
            or parsed.fragment
            or parsed.path not in {"", "/"}
        ):
            raise ValueError("HTTPS API origin required")
        self.api_key, self.base_url = api_key, base_url.rstrip("/")

    async def after_result(
        self, bot: Bot, telegram_user_id: object, event_id: str | int, language: str = "ru"
    ) -> dict[str, Any]:
        if (
            isinstance(telegram_user_id, bool)
            or not isinstance(telegram_user_id, int)
            or telegram_user_id <= 0
            or telegram_user_id > 2**53 - 1
        ):
            raise ValueError("A real Telegram user ID is required")
        if (
            isinstance(event_id, bool)
            or type(event_id) not in (str, int)
            or not re.fullmatch(r"[A-Za-z0-9:_-]{1,100}", str(event_id))
        ):
            raise ValueError("A stable event ID is required")
        async with httpx.AsyncClient(
            timeout=5, follow_redirects=False, headers={"X-PixorAds-Key": self.api_key}
        ) as client:
            root = self.base_url + "/api/v1/ad-network/publisher-api/bot"
            try:
                result = await client.post(
                    root + "/offer",
                    json={
                        "telegram_user_id": telegram_user_id,
                        "event_id": str(event_id),
                        "language": "ru" if language == "ru" else "en",
                        "trigger": "result_delivered",
                    },
                )
                result.raise_for_status()
                offer = _object(result.json())
                if offer["source"] != "pixorads":
                    return offer
                if not isinstance(offer.get("offer_id"), str):
                    raise TypeError("Invalid ad response")
                identity = str(UUID(offer["offer_id"]))
                raw_messages: object = offer["telegram_messages"]
                if not isinstance(raw_messages, list) or not raw_messages:
                    raise ValueError("Invalid ad response")
                messages = [_object(message) for message in cast(list[object], raw_messages)]
                if any(
                    message.get("method") not in ("sendMessage", "sendPhoto", "sendVideo")
                    or not isinstance(message.get("payload"), dict)
                    for message in messages
                ):
                    raise ValueError("Invalid ad response")
                claim = await client.post(f"{root}/offers/{identity}/claim")
                claim.raise_for_status()
                permission = _object(claim.json())
                if permission.get("send") is not True:
                    return {"source": "none", "reason": "event_already_used"}
            except (httpx.HTTPError, ValueError, KeyError, TypeError):
                return {"source": "none", "reason": "network_unavailable"}
            delivered = 0
            try:
                for message in messages:
                    method = {
                        "sendMessage": bot.send_message,
                        "sendPhoto": bot.send_photo,
                        "sendVideo": bot.send_video,
                    }[message["method"]]
                    payload: dict[str, Any] = {**message["payload"], "chat_id": telegram_user_id}
                    await method(**payload)
                    delivered += 1
            except (TelegramAPIError, OSError, TimeoutError) as error:
                # Only definite Telegram rejection frees the opportunity. Network
                # timeouts remain 'sending'; repeat calls cannot duplicate the ad.
                if delivered == 0 and isinstance(
                    error, (TelegramBadRequest, TelegramForbiddenError)
                ):
                    try:
                        await client.post(
                            f"{root}/offers/{identity}/report", json={"outcome": "failed"}
                        )
                    except httpx.HTTPError:
                        pass
                return {"source": "none", "reason": "send_failed_or_unknown", "offer_id": identity}
            try:
                report = await client.post(
                    f"{root}/offers/{identity}/report", json={"outcome": "sent"}
                )
                report.raise_for_status()
            except httpx.HTTPError:
                return {"source": "pixorads", "offer_id": identity, "report_pending": True}
            return {"source": "pixorads", "offer_id": identity, "report_pending": False}
