"""
Social Provider Base Class
Ported & simplified từ BrightBean Studio providers/base.py
Bỏ Django dependency, chuyển sang httpx async cho FastAPI
"""

from __future__ import annotations

import logging
from abc import ABC, abstractmethod
from typing import Any

import httpx

logger = logging.getLogger(__name__)

REQUEST_TIMEOUT = 30.0


class APIError(Exception):
    def __init__(self, message: str, status_code: int = 0, platform: str = "", raw_response: dict | None = None):
        super().__init__(message)
        self.status_code = status_code
        self.platform = platform
        self.raw_response = raw_response or {}


class RateLimitError(APIError):
    def __init__(self, message: str, retry_after: int | None = None, **kwargs):
        super().__init__(message, **kwargs)
        self.retry_after = retry_after


class SocialProvider(ABC):
    """
    Abstract base class cho tất cả social platform providers.
    Ported từ BrightBean Studio — simplified cho Canifa use case.
    Mục đích: publish outfit suggestions + thu thập social feedback.
    """

    def __init__(self, credentials: dict | None = None):
        self.credentials = credentials or {}

    @property
    @abstractmethod
    def platform_name(self) -> str:
        """Tên platform (vd: 'Facebook', 'Instagram', 'TikTok')."""

    @abstractmethod
    def get_profile(self, access_token: str) -> dict:
        """Lấy thông tin tài khoản đã kết nối."""

    @abstractmethod
    def publish_post(self, access_token: str, content: dict) -> dict:
        """
        Publish nội dung lên platform.
        content = {
            "text": str,
            "image_url": str | None,
            "link": str | None,
        }
        Returns: {"post_id": str, "url": str, "success": bool}
        """

    # ─────────────────────────────────────────
    # Optional methods (override khi cần)
    # ─────────────────────────────────────────

    def get_comments(self, access_token: str, post_id: str) -> list[dict]:
        """Lấy comments của một post. Override theo từng platform."""
        raise NotImplementedError(f"{self.platform_name} chưa hỗ trợ get_comments")

    def reply_comment(self, access_token: str, comment_id: str, text: str) -> dict:
        """Reply comment. Override theo từng platform."""
        raise NotImplementedError(f"{self.platform_name} chưa hỗ trợ reply_comment")

    def validate_token(self, access_token: str) -> bool:
        """Kiểm tra token còn hiệu lực không."""
        try:
            self.get_profile(access_token)
            return True
        except Exception:
            return False

    # ─────────────────────────────────────────
    # HTTP helper (sync — dùng cho background worker)
    # ─────────────────────────────────────────

    def _request(
        self,
        method: str,
        url: str,
        *,
        access_token: str | None = None,
        headers: dict | None = None,
        params: dict | None = None,
        json: dict | None = None,
        data: Any = None,
        files: dict | None = None,
        timeout: float = REQUEST_TIMEOUT,
    ) -> httpx.Response:
        """HTTP request với error handling chuẩn. Raises APIError / RateLimitError."""
        req_headers = {}
        if access_token:
            req_headers["Authorization"] = f"Bearer {access_token}"
        if headers:
            req_headers.update(headers)

        request_kwargs: dict = {
            "headers": req_headers,
            "params": params,
            "json": json,
            "files": files,
        }
        if isinstance(data, bytes):
            request_kwargs["content"] = data
        else:
            request_kwargs["data"] = data

        with httpx.Client(timeout=timeout) as client:
            response = client.request(method, url, **request_kwargs)

        if response.status_code == 429:
            retry_after = response.headers.get("Retry-After")
            raise RateLimitError(
                f"Rate limit {self.platform_name}: {response.text[:300]}",
                retry_after=int(retry_after) if retry_after else None,
                platform=self.platform_name,
                raw_response=self._safe_json(response),
            )

        if response.status_code >= 400:
            raise APIError(
                f"{self.platform_name} API {response.status_code}: {response.text[:300]}",
                status_code=response.status_code,
                platform=self.platform_name,
                raw_response=self._safe_json(response),
            )

        return response

    @staticmethod
    def _safe_json(response: httpx.Response) -> dict:
        try:
            return response.json()
        except Exception:
            return {}
