"""Instagram third-party API client for queue worker."""

from __future__ import annotations

import os
from typing import Any, Optional
from urllib.parse import quote

import aiohttp
from loguru import logger
from tenacity import retry, stop_after_attempt, wait_exponential


class InstagramClient:
    def __init__(self) -> None:
        self.api_key = os.getenv("INSTAGRAM_API_KEY", "123")
        self.user_base = os.getenv(
            "USER_RESOLVE_BASE", "https://api.virtualstore.uz/instagram-scraper"
        ).rstrip("/")
        self.media_base = os.getenv(
            "MEDIA_API_BASE", "https://api.brauzer.uz/instagram"
        ).rstrip("/")
        self._session: Optional[aiohttp.ClientSession] = None

    async def session(self) -> aiohttp.ClientSession:
        if self._session is None or self._session.closed:
            self._session = aiohttp.ClientSession(
                timeout=aiohttp.ClientTimeout(total=28),
                headers={"User-Agent": "KonkursWorker/1.0"},
            )
        return self._session

    async def close(self) -> None:
        if self._session and not self._session.closed:
            await self._session.close()

    @retry(stop=stop_after_attempt(3), wait=wait_exponential(min=1, max=6))
    async def _get(self, url: str) -> dict[str, Any]:
        s = await self.session()
        async with s.get(url) as resp:
            text = await resp.text()
            if resp.status >= 400:
                raise RuntimeError(f"HTTP {resp.status}: {text[:200]}")
            try:
                import orjson
                return orjson.loads(text)
            except Exception:
                import json
                return json.loads(text)

    async def resolve_user(self, username: str) -> dict[str, Any]:
        username = username.lstrip("@").strip().lower()
        url = f"{self.user_base}/users/resolve?user={quote(username)}"
        data = await self._get(url)
        if not data.get("id"):
            raise RuntimeError(f"User not found: {username}")
        return data

    async def check_follow(self, target_username: str, source_user_id: str) -> dict[str, Any]:
        target = target_username.lstrip("@").strip().lower()
        url = f"{self.media_base}/check-follow/{self.api_key}/{quote(target)}/{source_user_id}"
        data = await self._get(url)
        if data.get("status") != "success":
            raise RuntimeError(f"check_follow failed: {data}")
        return data

    async def check_like(self, username: str, media_url: str) -> dict[str, Any]:
        user = username.lstrip("@").strip().lower()
        encoded = quote(media_url, safe="")
        url = f"{self.media_base}/check-like/{self.api_key}/{quote(user)}/{encoded}"
        data = await self._get(url)
        if data.get("status") != "success":
            raise RuntimeError(f"check_like failed: {data}")
        return data

    async def check_comment(self, username: str, media_url: str) -> dict[str, Any]:
        user = username.lstrip("@").strip().lower()
        encoded = quote(media_url, safe="")
        url = f"{self.media_base}/check-comment/{self.api_key}/{quote(user)}/{encoded}"
        data = await self._get(url)
        if data.get("status") != "success":
            raise RuntimeError(f"check_comment failed: {data}")
        return data

    async def comment_info(self, media_id: str, comment_id: str) -> dict[str, Any]:
        url = f"{self.media_base}/comment-info/{self.api_key}/{media_id}/{comment_id}/"
        data = await self._get(url)
        if data.get("status") != "success":
            raise RuntimeError(f"comment_info failed: {data}")
        return data

    async def comment_replies(
        self, media_id: str, parent_id: str, max_pages: int = 2
    ) -> dict[str, Any]:
        url = (
            f"{self.media_base}/comment-replies/{self.api_key}/"
            f"{media_id}/{parent_id}?max_pages={max_pages}"
        )
        data = await self._get(url)
        if data.get("status") != "success":
            raise RuntimeError(f"comment_replies failed: {data}")
        return data

    async def media_info(self, media_url: str) -> dict[str, Any]:
        encoded = quote(media_url, safe="")
        url = f"{self.media_base}/media/{self.api_key}/{encoded}"
        data = await self._get(url)
        if data.get("status") != "success":
            raise RuntimeError(f"media_info failed: {data}")
        return data.get("media_details", data)
