import base64
import hashlib
import json
import time
from dataclasses import dataclass

import requests
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from commons_lang import object_utils

from language_translation.translate.provider.base import BaseProvider


@dataclass
class _TranslateKey:
    secret_key: str
    aes_key: str
    aes_iv: str


class YoudaoProvider(BaseProvider):

    def __init__(
            self,
            from_lang: str,
            to_lang: str,
            cookie: str = None,
            **kwargs
    ):
        if not cookie:
            raise ValueError("cookie is required")
        super().__init__(from_lang, to_lang, cookie, **kwargs)
        # self.timestamp = str(int(time.time() * 1000))

        self.headers = {
            "Cookie": self.cookie,
            "Referer": "https://fanyi.youdao.com/",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36"
        }

    @staticmethod
    def __get_sign(timestamp, secret_key: str):
        e = f"client=fanyideskweb&mysticTime={timestamp}&product=webfanyi&key={secret_key}"
        return hashlib.md5(e.encode()).hexdigest()

    def __get_translate_secret_key_response(self):
        timestamp = str(int(time.time() * 1000))
        yduuid = "asdjnjfenknafdfsdfsd"
        params = {
            "keyid": "webfanyi-key-getter",
            "sign": self.__get_sign(timestamp, yduuid),
            "client": "fanyideskweb",
            "product": "webfanyi",
            "appVersion": "1.0.0",
            "vendor": "web",
            "pointParam": "client,mysticTime,product",
            "mysticTime": timestamp,
            "keyfrom": "fanyi.web",
            "mid": "1",
            "screen": "1",
            "model": "1",
            "network": "wifi",
            "abtest": "0",
            "yduuid": "abcdefg"
        }
        response = requests.get("https://dict.youdao.com/webtranslate/key", params, headers=self.headers).json()
        data = object_utils.get(response, "data", {})
        if object_utils.is_not_empty(data):
            return _TranslateKey(
                secret_key=data["secretKey"],
                aes_key=data["aesKey"],
                aes_iv=data["aesIv"]
            )
        return None

    def __get_translate_response(self, text: str, translate_key: _TranslateKey):
        secret_key = translate_key.secret_key
        timestamp = str(int(time.time() * 1000))
        data = {
            "i": text,
            "from": self.from_lang,
            "to": self.to_lang,
            "domain": "0",
            "dictResult": "true",
            "keyid": "webfanyi",
            "sign": self.__get_sign(timestamp, secret_key),
            "client": "fanyideskweb",
            "product": "webfanyi",
            "appVersion": "1.0.0",
            "vendor": "web",
            "pointParam": "client,mysticTime,product",
            "mysticTime": timestamp,
            "keyfrom": "fanyi.web",
            "mid": "1",
            "screen": "1",
            "model": "1",
            "network": "wifi",
            "abtest": "0",
            "yduuid": "abcdefg",
        }
        return requests.post("https://dict.youdao.com/webtranslate", headers=self.headers, data=data).text

    @staticmethod
    def __encrypt_data(data: str, translate_key: _TranslateKey):
        aes_key = hashlib.md5(translate_key.aes_key.encode()).digest()
        aes_iv = hashlib.md5(translate_key.aes_iv.encode()).digest()
        cipher = AES.new(aes_key, AES.MODE_CBC, aes_iv)

        ciphertext = base64.urlsafe_b64decode(data)
        plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
        return plaintext.decode()

    def translate(self, text: str) -> str | None:
        translate_key = self.__get_translate_secret_key_response()
        resp = self.__get_translate_response(text, translate_key)
        if resp:
            data = self.__encrypt_data(resp, translate_key)
            results = object_utils.get(json.loads(data), "translateResult", [])
            if object_utils.is_not_empty(results):
                return object_utils.get(results[0][0], "tgt")
        return ""
