import logging
from typing import Any

import aiohttp

from config import settings

logger = logging.getLogger(__name__)


class APIClient:
    """HTTP client for backend API communication."""

    def __init__(self):
        self.base_url = settings.API_URL
        self._session: aiohttp.ClientSession | None = None
        logger.info(f"[APIClient] Initialized with base_url: {self.base_url}")

    async def _get_session(self) -> aiohttp.ClientSession:
        if self._session is None or self._session.closed:
            logger.info("[APIClient] Creating new aiohttp session")
            self._session = aiohttp.ClientSession()
        return self._session

    async def _request(
        self,
        method: str,
        endpoint: str,
        **kwargs
    ) -> dict[str, Any] | None:
        """Make HTTP request to backend API."""
        session = await self._get_session()
        url = f"{self.base_url}/api/v1{endpoint}"

        # Add bot secret header for authentication
        headers = kwargs.pop("headers", {})
        if settings.BOT_API_SECRET:
            headers["X-Bot-Secret"] = settings.BOT_API_SECRET

        logger.info(f"[APIClient] {method} {url}")
        if 'json' in kwargs:
            logger.info(f"[APIClient] Request body: {kwargs['json']}")
        if 'params' in kwargs:
            logger.info(f"[APIClient] Request params: {kwargs['params']}")

        try:
            async with session.request(method, url, headers=headers, **kwargs) as response:
                logger.info(f"[APIClient] Response status: {response.status}")
                response_text = await response.text()
                logger.info(f"[APIClient] Response body: {response_text[:500]}")

                if response.status == 200:
                    import json
                    return json.loads(response_text)
                elif response.status == 404:
                    logger.warning(f"[APIClient] 404 Not Found")
                    return None
                else:
                    logger.error(f"[APIClient] API error {response.status}: {response_text}")
                    return {"error": response_text}
        except aiohttp.ClientError as e:
            logger.error(f"[APIClient] Request failed: {e}")
            return {"error": str(e)}
        except Exception as e:
            logger.error(f"[APIClient] Unexpected error: {e}")
            return {"error": str(e)}

    async def confirm_telegram_link(
        self,
        token: str,
        telegram_id: int,
        telegram_username: str | None,
        telegram_first_name: str | None = None,
        telegram_last_name: str | None = None,
        telegram_avatar_url: str | None = None
    ) -> dict[str, Any]:
        """Confirm Telegram account linking."""
        result = await self._request(
            "POST",
            "/telegram/confirm-link",
            json={
                "token": token,
                "telegram_id": telegram_id,
                "telegram_username": telegram_username,
                "telegram_first_name": telegram_first_name,
                "telegram_last_name": telegram_last_name,
                "telegram_avatar_url": telegram_avatar_url
            }
        )
        return result or {"error": "Не удалось связаться с сервером"}

    async def get_user_by_telegram_id(self, telegram_id: int) -> dict[str, Any] | None:
        """Get user by Telegram ID."""
        return await self._request("GET", f"/telegram/user/{telegram_id}")

    async def unlink_telegram(self, telegram_id: int) -> dict[str, Any]:
        """Unlink Telegram account."""
        result = await self._request(
            "POST",
            f"/telegram/unlink/{telegram_id}"
        )
        return result or {"error": "Не удалось связаться с сервером"}

    async def get_user_marathons(self, telegram_id: int) -> list[dict[str, Any]]:
        """Get user's marathons."""
        result = await self._request("GET", f"/telegram/marathons/{telegram_id}")
        if isinstance(result, list):
            return result
        return result.get("marathons", []) if result else []

    async def get_marathon_details(
        self,
        marathon_id: int,
        telegram_id: int
    ) -> dict[str, Any] | None:
        """Get marathon details for user."""
        return await self._request(
            "GET",
            f"/telegram/marathon/{marathon_id}",
            params={"telegram_id": telegram_id}
        )

    async def get_user_stats(self, telegram_id: int) -> dict[str, Any] | None:
        """Get user's overall statistics."""
        return await self._request("GET", f"/telegram/stats/{telegram_id}")

    async def get_notification_settings(self, telegram_id: int) -> dict[str, Any] | None:
        """Get user's notification settings."""
        return await self._request("GET", f"/telegram/notifications/{telegram_id}")

    async def update_notification_settings(
        self,
        telegram_id: int,
        settings: dict[str, bool]
    ) -> dict[str, Any] | None:
        """Update user's notification settings."""
        return await self._request(
            "PATCH",
            f"/telegram/notifications/{telegram_id}",
            json=settings
        )

    async def close(self):
        """Close the HTTP session."""
        if self._session and not self._session.closed:
            await self._session.close()


# Global API client instance
api_client = APIClient()
