"""Cookie Cloud 模块 - 从 Cookie Cloud 服务器获取 cookie 数据"""
import json
import hashlib
import base64
from typing import Dict, List, Optional, Tuple
import urllib.request
import urllib.error
from Crypto.Cipher import AES
from applogger import get_logger

logger = get_logger(__name__)


class CookieCloud:
    """Cookie Cloud 客户端"""

    def __init__(self, api_url: str, uuid: str, password: str):
        """
        初始化 Cookie Cloud 客户端

        Args:
            api_url: Cookie Cloud API 地址
            uuid: 用户 UUID
            password: 用户密码
        """
        self.api_url = api_url.rstrip('/')
        self.uuid = uuid
        self.password = password

    def _get_crypt_key(self) -> bytes:
        """生成加密密钥"""
        combined_string = f"{self.uuid}-{self.password}"
        return hashlib.md5(combined_string.encode('utf-8')).hexdigest()[:16].encode("utf-8")

    def _bytes_to_key(self, data: bytes, salt: bytes, output: int = 48) -> bytes:
        """OpenSSL EVP_BytesToKey 密钥派生算法"""
        assert len(salt) == 8, len(salt)
        data += salt
        key = hashlib.md5(data).digest()
        final_key = key
        while len(final_key) < output:
            key = hashlib.md5(key + data).digest()
            final_key += key
        return final_key[:output]

    def _decrypt(self, encrypted: str, passphrase: bytes) -> bytes:
        """解密数据"""
        encrypted_bytes = base64.b64decode(encrypted)
        assert encrypted_bytes.startswith(b"Salted__"), "Invalid encrypted data format"
        salt = encrypted_bytes[8:16]
        key_iv = self._bytes_to_key(passphrase, salt, 32 + 16)
        key = key_iv[:32]
        iv = key_iv[32:]
        aes = AES.new(key, AES.MODE_CBC, iv)
        decrypted_padded = aes.decrypt(encrypted_bytes[16:])
        padding_length = decrypted_padded[-1]
        if isinstance(padding_length, str):
            padding_length = ord(padding_length)
        return decrypted_padded[:-padding_length]

    def _download_data(self) -> Tuple[Optional[Dict], str]:
        """下载并解密所有数据"""
        try:
            url = f"{self.api_url}/get/{self.uuid}"
            request = urllib.request.Request(
                url,
                headers={
                    'Content-Type': 'application/json',
                    'User-Agent': 'CookieCloud-Client/1.0'
                },
                method='GET'
            )
            
            response = urllib.request.urlopen(request, timeout=30)
            
            if response.status != 200:
                return None, f"服务器返回错误状态码: {response.status}"
            
            result = json.loads(response.read().decode('utf-8'))
            
            if not result:
                return None, "服务器返回数据为空"
            
            encrypted = result.get("encrypted")
            if not encrypted:
                return None, "未获取到cookie密文"
            
            crypt_key = self._get_crypt_key()
            try:
                decrypted_data = self._decrypt(encrypted, crypt_key)
                result = json.loads(decrypted_data.decode("utf-8"))
            except Exception as e:
                return None, f"cookie解密失败: {str(e)}"
            
            if not result:
                return None, "cookie解密为空"
            
            return result, ""
            
        except urllib.error.HTTPError as e:
            return None, f"HTTP错误: {e.code} {e.reason}"
        except urllib.error.URLError as e:
            return None, f"网络连接失败: {e.reason}"
        except Exception as e:
            return None, f"下载失败: {str(e)}"

    def get_cookies(self) -> Dict[str, List[Dict]]:
        """
        从 Cookie Cloud 服务器获取 cookie 数据

        Returns:
            按域名分组的 cookie 数据字典
            格式: {"domain.com": [{"name": "cookie1", "value": "val1", ...}, ...], ...}
        """
        data, error = self._download_data()
        
        if error:
            logger.error(error)
            return {}
        
        # 处理数据结构
        cookie_data = {}
        
        # 兼容直接按域名分组的格式
        if isinstance(data, dict) and not data.get('cookie_data'):
            cookie_data = data
        # 兼容包含 cookie_data 的格式
        elif isinstance(data, dict) and data.get('cookie_data'):
            cookie_data = data.get('cookie_data', {})
        
        # 处理 sameSite 字段
        processed_cookies = {}
        for domain, cookies in cookie_data.items():
            if not cookies:
                continue
            processed_cookies[domain] = []
            for cookie in cookies:
                if cookie.get('sameSite') == 'unspecified':
                    cookie['sameSite'] = 'Lax'
                processed_cookies[domain].append(cookie)
        
        return processed_cookies

    def get_cookies_for_domain(self, domain: str) -> List[Dict]:
        """
        获取指定域名的 cookie

        Args:
            domain: 域名

        Returns:
            cookie 列表
        """
        all_cookies = self.get_cookies()
        
        matched_cookies = []
        for cookie_domain, cookies in all_cookies.items():
            clean_domain = cookie_domain.lstrip('.')
            if domain in clean_domain or clean_domain in domain:
                matched_cookies.extend(cookies)
        
        return matched_cookies


if __name__ == "__main__":
    cc = CookieCloud(
        api_url="https://movie-pilot.org/cookiecloud",
        uuid="hu6n2vcUmzpu7mqUN2rVCg",
        password="jtDM5dV9AyqXkZdQVeA9f6"
    )
    
    cookies = cc.get_cookies()
    logger.info(f"获取到 {len(cookies)} 个域名的 cookies")
    
    lmkbi_cookies = cc.get_cookies_for_domain('lmkbi.95155.com')
    logger.info(f"获取到 {len(lmkbi_cookies)} 个 lmkbi.95155.com 的 cookies")
