"""
角色卡格式转换器
支持 SillyTavern V2/V3 格式与内部格式的双向转换
"""
import json
import base64
from typing import Optional, Dict, Any
from pathlib import Path
from PIL import Image
import io

try:
    from backend.models.internal import CharacterCard
except ImportError:
    from models.internal import CharacterCard


class CharacterCardConverter:
    """角色卡格式转换器"""
    
    @staticmethod
    def st_to_internal(st_data: dict, avatar_path: Optional[str] = None) -> CharacterCard:
        """
        SillyTavern 格式 → 内部格式
        
        Args:
            st_data: SillyTavern 角色卡数据（V2/V3）
            avatar_path: 头像路径（可选）
        
        Returns:
            CharacterCard 对象
        """
        import uuid
        from datetime import datetime
        
        # 兼容两种传入方式：完整ST格式或直接data
        if 'spec' in st_data:
            data = st_data.get('data', {})
        else:
            data = st_data
        
        extensions = data.get('extensions', {})
        
        return CharacterCard(
            id=str(uuid.uuid4()),
            name=data['name'],
            description=data.get('description', ''),
            personality=data.get('personality', ''),
            scenario=data.get('scenario', ''),
            first_mes=data.get('first_mes', ''),
            mes_example=data.get('mes_example', ''),
            categories=[],  # ST没有categories
            tableHeaders=[],  # ST没有tableHeaders
            worldInfoId=extensions.get('world'),
            outputSchema=None,  # ST不支持结构化输出
            avatarPath=avatar_path,
            alternate_greetings=data.get('alternate_greetings', []),
            tags=data.get('tags', []),
            createdAt=int(datetime.now().timestamp()),
            updatedAt=int(datetime.now().timestamp()),
            lastChatAt=None,
            isFavorite=extensions.get('fav', False),
            version=1
        )
    
    @staticmethod
    def internal_to_st(character: CharacterCard) -> dict:
        """
        内部格式 → SillyTavern V3 格式
        
        Args:
            character: CharacterCard 对象
        
        Returns:
            SillyTavern V3 格式字典
        """
        return {
            "spec": "chara_card_v3",
            "spec_version": "3.0",
            "data": {
                "name": character.name,
                "description": character.description,
                "personality": character.personality,
                "scenario": character.scenario,
                "first_mes": character.first_mes,
                "mes_example": character.mes_example,
                "alternate_greetings": character.alternate_greetings or [],
                "tags": character.tags or [],
                "creator_notes": "",
                "system_prompt": "",
                "post_history_instructions": "",
                "extensions": {
                    "world": character.worldInfoId,
                    "talkativeness": 0.5,
                    "fav": character.isFavorite
                }
            }
        }
    
    @staticmethod
    def export_as_png(character: CharacterCard, avatar_path: Optional[str] = None, use_default_avatar: bool = False) -> bytes:
        """
        导出为 SillyTavern PNG 格式
        
        Args:
            character: CharacterCard 对象
            avatar_path: 头像图片路径（可选）
            use_default_avatar: 是否使用默认头像（不嵌入JSON数据）
        
        Returns:
            PNG 文件的二进制数据
        """
        # 1. 创建/加载图片
        if avatar_path and Path(avatar_path).exists():
            img = Image.open(avatar_path)
        else:
            # 创建默认图片（400x600像素，灰色背景）
            img = Image.new('RGB', (400, 600), color=(73, 109, 137))
        
        # 确保是 RGBA 模式
        if img.mode != 'RGBA':
            img = img.convert('RGBA')
        
        # 2. 如果不是默认头像，才嵌入 JSON 数据
        if not use_default_avatar:
            st_data = CharacterCardConverter.internal_to_st(character)
            json_str = json.dumps(st_data, ensure_ascii=False)
            base64_data = base64.b64encode(json_str.encode('utf-8')).decode('ascii')
            img.text['ccv3'] = base64_data
        
        # 3. 保存到字节流
        buffer = io.BytesIO()
        img.save(buffer, format='PNG')
        buffer.seek(0)
        
        return buffer.read()
    
    @staticmethod
    def extract_from_png(png_data: bytes) -> Optional[dict]:
        """
        从 PNG 文件中提取嵌入的角色数据
        
        Args:
            png_data: PNG 文件的二进制数据
        
        Returns:
            SillyTavern 格式字典，如果没有嵌入数据则返回 None
        """
        try:
            img = Image.open(io.BytesIO(png_data))
            
            # 尝试 V3 格式 (ccv3)
            if 'ccv3' in img.text:
                json_str = base64.b64decode(img.text['ccv3']).decode('utf-8')
                return json.loads(json_str)
            
            # 尝试 V2 格式 (chara)
            elif 'chara' in img.text:
                json_str = base64.b64decode(img.text['chara']).decode('utf-8')
                return json.loads(json_str)
            
            # 没有嵌入数据
            return None
        
        except Exception as e:
            print(f"解析PNG失败: {e}")
            return None
