"""
火山引擎 MediaKit Provider
===========================

直接封装火山引擎 MediaKit HTTP API：
- 图像背景移除（/api/v1/tools/remove-image-background/sync）

使用 httpx.AsyncClient，支持外部注入（由 lifespan 管理生命周期）。
"""

from __future__ import annotations

import logging
from typing import Any

import httpx

from app.config import get_settings
from app.core.exceptions import PlatformError, PlatformErrorType

logger = logging.getLogger(__name__)


def _map_mediakit_error(status: int, message: str, code: int | None = None) -> PlatformError:
    """把 MediaKit 错误映射为标准 PlatformError"""
    error_mapping = {
        400: (PlatformErrorType.BAD_REQUEST, False),
        401: (PlatformErrorType.AUTH_FAILED, False),
        403: (PlatformErrorType.AUTH_FAILED, False),
        429: (PlatformErrorType.RATE_LIMIT, True),
        500: (PlatformErrorType.SERVER_ERROR, True),
        502: (PlatformErrorType.SERVER_ERROR, True),
        503: (PlatformErrorType.SERVER_ERROR, True),
    }
    error_type, retryable = error_mapping.get(status, (PlatformErrorType.UNKNOWN, False))
    return PlatformError(
        message, platform="volcengine_mediakit",
        retryable=retryable, error_type=error_type,
        status_code=status,
    )


class VolcengineMediakitProvider:
    """火山引擎 MediaKit Provider

    直接调用 MediaKit HTTP API，不做业务层处理。
    """

    BASE_URL = "https://mediakit.cn-beijing.volces.com"
    REMOVE_BG_PATH = "/api/v1/tools/remove-image-background/sync"
    DEFAULT_TIMEOUT = 60.0

    def __init__(
        self,
        token: str | None = None,
        client: httpx.AsyncClient | None = None,
    ):
        settings = get_settings()
        self.token = token or settings.VOLCENGINE_MEDIAKIT_TOKEN or ""

        if not self.token:
            raise PlatformError(
                "VOLCENGINE_MEDIAKIT_TOKEN 未配置",
                platform="volcengine_mediakit",
                retryable=False,
                error_type=PlatformErrorType.BAD_REQUEST,
            )

        if client is not None:
            self.client = client
            self._owns_client = False
        else:
            self.client = httpx.AsyncClient(timeout=self.DEFAULT_TIMEOUT)
            self._owns_client = True

    def _get_headers(self) -> dict:
        return {
            "Authorization": f"Bearer; {self.token}",
            "Content-Type": "application/json",
        }

    async def close(self) -> None:
        """关闭 HTTP 客户端"""
        if self._owns_client and self.client and not self.client.is_closed:
            await self.client.aclose()

    async def remove_background(
        self,
        image_url: str,
        scene: str = "general",
        need_contour: bool = False,
        contour_color: str = "#FFFFFF",
        contour_size: int = 10,
        need_crop_background: bool = False,
    ) -> dict[str, Any]:
        """同步抠图，返回原始 JSON

        Args:
            image_url: 原始图片 URL
            scene: 场景类型
            need_contour: 是否为主体生成描边（仅 human/product 场景生效）
            contour_color: 描边颜色，十六进制 RGB 格式
            contour_size: 描边宽度（px），范围 [1, 100]
            need_crop_background: 是否裁剪透明背景到刚好包裹主体

        Returns:
            {"code": 0, "message": "Success", "data": {"image_url": "https://..."}}
        """
        payload: dict[str, Any] = {"image_url": image_url, "scene": scene}
        if need_contour:
            payload["need_contour"] = True
            payload["contour_color"] = contour_color
            payload["contour_size"] = max(1, min(100, contour_size))
        if need_crop_background:
            payload["need_crop_background"] = True

        try:
            response = await self.client.post(
                f"{self.BASE_URL}{self.REMOVE_BG_PATH}",
                json=payload,
                headers=self._get_headers(),
            )
            response.raise_for_status()
            data = response.json()

            # 火山引擎 MediaKit 有两种响应格式：
            # 格式1: {"code": 0, "message": "...", "data": {...}}
            # 格式2: {"success": true, "result": {...}, "expires_at": ...}
            code = data.get("code")
            if code is not None:
                # 格式1
                if code != 0:
                    logger.warning(
                        f"[MediaKit] 抠图业务失败: code={code}, "
                        f"message={data.get('message', 'N/A')}, "
                        f"raw_response={data}, image_url={image_url[:80]}..."
                    )
                    raise _map_mediakit_error(
                        response.status_code,
                        data.get("message", f"抠图失败: code={code}"),
                        code=code,
                    )
                return data
            else:
                # 格式2
                if not data.get("success", False):
                    logger.warning(
                        f"[MediaKit] 抠图业务失败: success=false, "
                        f"raw_response={data}, image_url={image_url[:80]}..."
                    )
                    raise _map_mediakit_error(
                        response.status_code,
                        "抠图失败: 平台返回失败状态",
                    )
                # 将格式2标准化为格式1，方便上层统一处理
                return {
                    "code": 0,
                    "message": "Success",
                    "data": data.get("result", {}),
                }

        except PlatformError:
            raise
        except httpx.HTTPStatusError as e:
            raise _map_mediakit_error(
                e.response.status_code, f"HTTP错误: {e.response.status_code}"
            ) from e
        except (httpx.NetworkError, httpx.TimeoutException) as e:
            raise PlatformError(
                f"MediaKit 网络错误: {e}", platform="volcengine_mediakit",
                retryable=True, error_type=PlatformErrorType.TIMEOUT,
            ) from e
        except Exception as e:
            raise _map_mediakit_error(500, f"抠图失败: {str(e)}") from e
