"""Volcano Engine ARK video generation API client."""

import requests
from django.conf import settings


# API error code → user-friendly Chinese message
ERROR_MESSAGES = {
    # Input content moderation — 人脸/敏感内容
    'InputImageSensitiveContentDetected.PrivacyInformation': '参考图片中检测到真实人脸，请使用虚拟人像素材替代真人照片',
    'InputImageSensitiveContentDetected': '参考图片包含敏感内容，请更换图片后重试',
    'InputVideoSensitiveContentDetected.PrivacyInformation': '参考视频中检测到真实人脸，请使用虚拟人像素材替代真人视频',
    'InputVideoSensitiveContentDetected': '参考视频包含敏感内容，请更换视频后重试',
    'InputTextSensitiveContentDetected': '提示词包含敏感内容，请修改后重试',
    'InputAudioSensitiveContentDetected': '参考音频包含敏感内容，请更换音频后重试',
    # Output content moderation
    'OutputVideoSensitiveContentDetected': '生成的视频包含敏感内容，已被系统拦截，请修改提示词后重试',
    'OutputVideoSensitiveContentDetected.PolicyViolation': '生成的视频涉及版权限制内容（如知名IP、名人肖像等），已被系统拦截，请修改提示词后重试',
    'OutputImageSensitiveContentDetected': '生成的图片包含敏感内容，已被系统拦截',
    # Parameter errors
    'InvalidParameter': '请求参数无效，请检查输入内容',
    'InvalidImage': '图片格式或尺寸不符合要求，请检查后重试',
    'InvalidVideo': '视频格式或尺寸不符合要求，请检查后重试',
    'InvalidAudio': '音频格式不符合要求，请检查后重试',
    'AudioDurationExceeded': '音频总时长超过15秒限制，请缩短音频后重试',
    'AudioFormatNotSupported': '音频格式不支持，请使用 MP3 或 WAV 格式',
    # Rate limit
    'RateLimitExceeded': '请求过于频繁，请稍后重试',
    'ConcurrencyLimitExceeded': '当前生成任务过多，请稍后重试',
    # Account & billing
    'InsufficientBalance': '平台账户余额不足，请联系管理员',
    # Asset errors
    'AssetNotFound': '引用的素材不存在或已被删除，请检查素材库',
    # Server errors
    'ServerOverloaded': '服务器繁忙，请稍后重试',
    'InternalError': '视频生成服务异常，请稍后重试',
    'Timeout': '生成超时，请重试',
}

# 关键词匹配：API 返回的 message 中包含这些关键词时，映射为对应中文提示
_MESSAGE_KEYWORDS = {
    'face': '检测到真实人脸，请使用虚拟人像素材替代真人照片',
    'privacy': '检测到真实人脸，请使用虚拟人像素材替代真人照片',
    'sensitive': '内容包含敏感信息，请修改后重试',
    'not found': '引用的素材不存在或已被删除，请检查素材库',
    'not valid': '请求参数无效，请检查输入内容',
    'audio duration': '音频总时长超过15秒限制，请缩短音频后重试',
    'audio': '音频不符合要求（支持MP3/WAV，单条2-15秒，总时长≤15秒）',
}


class AirDramaAPIError(Exception):
    """Raised when video generation API returns an error response."""
    def __init__(self, code, message, status_code=400):
        self.code = code
        self.api_message = message
        self.status_code = status_code
        # 1. 精确匹配 error code
        friendly = ERROR_MESSAGES.get(code)
        if not friendly:
            # 2. 关键词匹配 message 内容
            msg_lower = (message or '').lower()
            for keyword, hint in _MESSAGE_KEYWORDS.items():
                if keyword in msg_lower:
                    friendly = hint
                    break
        self.user_message = friendly or '生成失败，请重试'
        super().__init__(self.user_message)


MODEL_MAP = {
    'seedance_2.0': 'doubao-seedance-2-0-260128',
    'seedance_2.0_fast': 'doubao-seedance-2-0-fast-260128',
}

# 推理接入点优先：有 EP 用 EP，没有降级到模型 ID
def _resolve_model(model):
    ep_map = {
        'seedance_2.0': settings.ARK_ENDPOINT_SEEDANCE,
        'seedance_2.0_fast': settings.ARK_ENDPOINT_SEEDANCE_FAST,
    }
    ep = ep_map.get(model, '')
    if ep:
        return ep
    return MODEL_MAP.get(model, model)


def _headers():
    return {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {settings.ARK_API_KEY}',
    }


def create_task(prompt, model, content_items, aspect_ratio, duration, resolution,
                generate_audio=True, search_mode='off', seed=-1):
    """Create a video generation task.

    Args:
        prompt: Text prompt for video generation.
        model: Model key ('airdrama' or 'airdrama_fast').
        content_items: List of media content dicts (image_url, video_url, audio_url).
        aspect_ratio: Video aspect ratio ('16:9', '9:16', etc.).
        duration: Video duration in seconds.
        resolution: Output video resolution ('480p'|'720p'|'1080p'). 必填，不设默认值避免调用者遗漏导致
            静默降级（1080p 任务若因默认值被意外降为 720p 会产生计费偏差，违反准确性原则）。
            注意：1080p 仅 Seedance 2.0 支持。
        generate_audio: Whether to generate audio with the video.
        search_mode: 'smart' to enable internet search, 'off' to disable.

    Returns:
        dict: API response with task id and status.
    """
    url = f'{settings.ARK_BASE_URL}/contents/generations/tasks'

    content = []
    if prompt:
        content.append({'type': 'text', 'text': prompt})
    content.extend(content_items)

    payload = {
        'model': _resolve_model(model),
        'content': content,
        'generate_audio': generate_audio,
        'ratio': aspect_ratio,
        'resolution': resolution,
        'duration': duration,
        'watermark': False,
        'seed': seed,
    }

    if search_mode and search_mode != 'off':
        payload['tools'] = [{'type': 'web_search'}]

    import logging
    logger = logging.getLogger(__name__)
    logger.info('AirDrama API payload: %s', {k: v for k, v in payload.items() if k != 'content'})
    # 记录 content 中的非文本项，方便排查素材引用问题
    media_items = [ci for ci in content if ci.get('type') != 'text']
    if media_items:
        logger.info('AirDrama content media items (%d): %s', len(media_items), media_items)

    resp = requests.post(url, json=payload, headers=_headers(), timeout=60)
    if resp.status_code != 200:
        # Extract human-readable error from API response
        try:
            err = resp.json().get('error', {})
            code = err.get('code', '')
            message = err.get('message', resp.text)
            logger.error('AirDrama API error: status=%s code=%s message=%s', resp.status_code, code, message)
        except Exception:
            code, message = '', resp.text
            logger.error('AirDrama API error: status=%s body=%s', resp.status_code, resp.text)
        raise AirDramaAPIError(code, message, resp.status_code)
    return resp.json()


def query_task(task_id):
    """Query a video generation task by its ARK task ID.

    Returns:
        dict: Task status, content (video URL on success), usage info.
    """
    url = f'{settings.ARK_BASE_URL}/contents/generations/tasks/{task_id}'
    resp = requests.get(url, headers=_headers(), timeout=30)
    resp.raise_for_status()
    return resp.json()


def extract_video_url(task_response):
    """Extract the video URL from a completed task response."""
    content = task_response.get('content')
    if not content:
        return None

    # content could be a list of items or a dict
    if isinstance(content, list):
        for item in content:
            if item.get('type') == 'video_url':
                return item.get('video_url', {}).get('url')
    elif isinstance(content, dict):
        if 'video_url' in content:
            url = content['video_url']
            return url.get('url') if isinstance(url, dict) else url

    return None


def map_status(ark_status):
    """Map ARK task status to our DB status."""
    mapping = {
        'running': 'processing',
        'submitted': 'queued',
        'queued': 'queued',
        'succeeded': 'completed',
        'failed': 'failed',
    }
    return mapping.get(ark_status, 'processing')
