import datetime
from urllib import parse as urllib

from passerelle.base import signature


def test_signature():
    KEY = 'xyz'
    STRING = 'aaa'
    URL = 'http://example.net/api/?coucou=zob'
    QUERY = 'coucou=zob'
    OTHER_KEY = 'abc'

    # Passing test
    assert signature.check_string(STRING, signature.sign_string(STRING, KEY), KEY)
    assert signature.check_query(signature.sign_query(QUERY, KEY), KEY)
    assert signature.check_url(signature.sign_url(URL, KEY), KEY)

    # Not passing tests
    assert not signature.check_string(STRING, signature.sign_string(STRING, KEY), OTHER_KEY)
    assert not signature.check_query(signature.sign_query(QUERY, KEY), OTHER_KEY)
    assert not signature.check_url(signature.sign_url(URL, KEY), OTHER_KEY)
    assert not signature.check_url('%s&foo=bar' % signature.sign_url(URL, KEY), KEY)

    # Test URL is preserved
    assert URL in signature.sign_url(URL, KEY)
    assert QUERY in signature.sign_query(QUERY, KEY)

    # Test signed URL expected parameters
    assert '&algo=sha256&' in signature.sign_url(URL, KEY)
    assert '&timestamp=' in signature.sign_url(URL, KEY)
    assert '&nonce=' in signature.sign_url(URL, KEY)

    # Test unicode key conversion to UTF-8
    assert signature.check_url(signature.sign_url(URL, '\xe9\xe9'), b'\xc3\xa9\xc3\xa9')
    assert signature.check_url(signature.sign_url(URL, b'\xc3\xa9\xc3\xa9'), '\xe9\xe9')

    # Test timedelta parameter
    now = datetime.datetime.utcnow()
    assert '&timestamp=%s' % urllib.quote(now.strftime('%Y-%m-%dT%H:%M:%SZ')) in signature.sign_url(
        URL, KEY, timestamp=now
    )

    # Test nonce parameter
    assert '&nonce=uuu&' in signature.sign_url(URL, KEY, nonce='uuu')
    assert '&nonce=' in signature.sign_url(URL, KEY)
    assert '&nonce=' not in signature.sign_url(URL, KEY, nonce='')

    # Test known_nonce
    def known_nonce(nonce):
        return nonce == 'xxx'

    assert signature.check_url(signature.sign_url(URL, KEY), KEY, known_nonce=known_nonce)
    assert signature.check_url(signature.sign_url(URL, KEY, nonce='zzz'), KEY, known_nonce=known_nonce)
    assert not signature.check_url(signature.sign_url(URL, KEY, nonce='xxx'), KEY, known_nonce=known_nonce)
    assert not signature.check_url(signature.sign_url(URL, KEY, nonce=''), KEY, known_nonce=known_nonce)

    # Test timedelta
    now = datetime.datetime.utcnow() - datetime.timedelta(seconds=20)
    assert signature.check_url(signature.sign_url(URL, KEY, timestamp=now), KEY)
    now = datetime.datetime.utcnow() + datetime.timedelta(seconds=20)
    assert signature.check_url(signature.sign_url(URL, KEY, timestamp=now), KEY)
    # too late
    now = datetime.datetime.utcnow() - datetime.timedelta(seconds=40)
    assert not signature.check_url(signature.sign_url(URL, KEY, timestamp=now), KEY)
    now = datetime.datetime.utcnow() - datetime.timedelta(seconds=20)
    assert not signature.check_url(signature.sign_url(URL, KEY, timestamp=now), KEY, timedelta=10)
    # too early
    now = datetime.datetime.utcnow() + datetime.timedelta(seconds=40)
    assert not signature.check_url(signature.sign_url(URL, KEY, timestamp=now), KEY)
