import base64
import os

import pybase64
from clarabot_nano_common.utility.serialize import (
    msgpack_loads,
    msgpack_loads_strict_map_key,
    bigger_int_from_js_msgpack,
    data_length_of_base64,
    hs256_sign,
    hs256_verify,
)


def test_msgpack_ext_hook():
    ext_18 = b"\xc7\x06\x12\x01\x02\x03\x04\x05\x06"
    ext_26 = b"\xc7\x06\x1a\x01\x02\x03\x04\x05\x06"
    for loads in [msgpack_loads, msgpack_loads_strict_map_key]:
        assert loads(ext_18) == b"\x01\x02\x03\x04\x05\x06"
        assert loads(ext_26) == b"\x01\x02\x03\x04\x05\x06"


def test_bigger_int_from_js_msgpack():
    assert bigger_int_from_js_msgpack(1619720759111.0) == 1619720759111
    assert bigger_int_from_js_msgpack(1619720759111) == 1619720759111
    assert bigger_int_from_js_msgpack(1619720759111.001) == 1619720759111.001
    assert bigger_int_from_js_msgpack(None) is None
    assert bigger_int_from_js_msgpack("asd") == "asd"


def test_serialize_base64():
    for i in range(24):
        v = os.urandom(i)
        b = base64.b64encode(v)
        assert b == pybase64.b64encode(v)
        assert v == pybase64.b64decode(b)
        b = base64.urlsafe_b64encode(v)
        assert b == pybase64.urlsafe_b64encode(v)
        assert v == pybase64.urlsafe_b64decode(b)


def test_data_length_of_base64():
    for value, padding in [("x", "="), (b"x", b"=")]:
        for blocks in range(10):
            vp = blocks * (4 * value)  # value prefix for blocks
            lp = blocks * 3  # length from prefix
            assert data_length_of_base64(vp) == lp + 0
            # assert data_length_of_base64(vp + value])) == lp + 1  # malformed
            # assert data_length_of_base64(vp + value + padding])) == lp + 1  # malformed
            # assert data_length_of_base64(vp + value + padding + padding])) == lp + 2  # malformed
            # assert data_length_of_base64(vp + value + padding + padding + padding])) == lp + 3  # malformed
            assert data_length_of_base64(vp + value + value) == lp + 1  # no padding
            # assert data_length_of_base64(vp + value + value + padding])) == lp + 2  # malformed
            assert data_length_of_base64(vp + value + value + padding + padding) == lp + 1
            assert data_length_of_base64(vp + value + value + value) == lp + 2  # no padding
            assert data_length_of_base64(vp + value + value + value + padding) == lp + 2
            assert data_length_of_base64(vp + value + value + value + value) == lp + 3


def test_hs256_sign_verify():
    k = b"a" * 32
    d = {"a": 55, "xxx": b"ok"}
    x = hs256_sign(k, d)
    assert x == "gqFhN6N4eHjEAm9r.K2Y3-nt9FDBtGmaVNTxZarj9oTgmiOMH4RmOTKhmFQ4"
    assert d == hs256_verify(k, x)
