import base64
import random
import string
from functools import lru_cache

from libretranslate.storage import get_storage


def to_base(n, b):
    if n == 0:
        return 0
    if n < 0:
        sign = -1
    else:
        sign = 1
    
    n *= sign
    digits = []
    while n:
        digits.append(str(n % b))
        n //= b
    return int(''.join(digits[::-1])) * sign

@lru_cache(maxsize=4)
def obfuscate(input_str):
    encoded = [ord(ch) for ch in input_str]
    ops = ['+', '-', '*', '']
    parts = []

    for c in encoded:
        num = random.randint(1, 100)
        op = random.choice(ops)
        if op == '+':
            v = c + num
            op = '-'
        elif op == '-':
            v = c - num
            op = '+'
            if random.randint(0, 1) == 0:
                op = '+false+'
        elif op == '*':
            v = c * num
            op = '/'
            if random.randint(0, 1) == 0:
                op = '/**\\/*//'

        use_dec = random.randint(0, 1) == 0
        base = random.randint(4, 7)

        if op == '':
            if use_dec:
                parts.append(f'_({c})')
            else:
                parts.append(f'_(p({to_base(c, base)},{base}))')
        else:
            if use_dec:
                parts.append(f'_({v}{op}{num})')
            else:
                parts.append(f'_(p({to_base(v, base)},{base}){op}p({to_base(num,base)},{hex(base)}))')

    for i in range(int(len(encoded) / 3)):
        c = random.randint(1, 100)
        parts.insert(random.randint(0, len(parts)), f"_(/*_({c})*/)")
    for i in range(int(len(encoded) / 3)):
        parts.insert(random.randint(0, len(parts)), f"\n[]\n")
    
    code = '(_=String.fromCharCode,p=parseInt,' + '+'.join(parts) + ')'
    return code

def generate_secret():
    return ''.join(random.choices(string.ascii_uppercase + string.digits, k=7))

def rotate_secrets():
    s = get_storage()
    secret_1 = s.get_str("secret_1")
    s.set_str("secret_0", secret_1)
    s.set_str("secret_1", generate_secret())

def secret_match(secret):
    s = get_storage()
    return secret == s.get_str("secret_0") or secret == s.get_str("secret_1")

def secret_bogus_match(secret):
    if random.randint(0, 1) == 0:
        return secret == get_bogus_secret()
    return False

def get_current_secret():
    return get_storage().get_str("secret_1")

def get_current_secret_b64():
    return base64.b64encode(get_current_secret().encode("utf-8")).decode("utf-8")

def get_current_secret_js():
    return obfuscate(get_current_secret_b64())

def get_bogus_secret():
    return get_storage().get_str("secret_bogus")

def get_bogus_secret_b64():
    return base64.b64encode(get_bogus_secret().encode("utf-8")).decode("utf-8")

def get_bogus_secret_js():
    return obfuscate(get_bogus_secret_b64())

@lru_cache(maxsize=1)
def get_emoji():
    return random.choice(["😂", "🤪", "😜", "🤣", "😹", "🐒", "🙈", "🤡", "🥸", "😆", "🥴", "🐸", "🐤", "🐒🙊", "👀", "💩", "🤯", "😛", "🤥", "👻"])

def setup(args):
    if args.require_api_key_secret:
        s = get_storage()

        if not s.exists("secret_0"):
            s.set_str("secret_0", generate_secret())

        if not s.exists("secret_1"):
            s.set_str("secret_1", generate_secret())

        if not s.exists("secret_bogus"):
            s.set_str("secret_bogus", generate_secret())
