# coding=utf-8
"""
run the test from the src/invesytoolbox directory:
pytest ../tests/test_security.py -v
"""

import pytest
from invesytoolbox.itb_security import check_password_security, create_key, create_secure_key


def test_create_secure_key():
    key = create_secure_key()
    assert isinstance(key, str)
    assert len(key) > 0

    key = create_secure_key(bits=128)
    assert isinstance(key, str)
    # 128 bits = 16 bytes = 32 hex chars
    assert len(key) == 32

    key = create_secure_key(max_len=10)
    assert len(key) == 10

    key = create_secure_key(max_len=5)
    assert len(key) == 5

    key = create_secure_key(key='my-predefined-key')
    assert key == 'my-predefined-key'

    key = create_secure_key(key='my-predefined-key', max_len=5)
    assert key == 'my-pr'

    # bits not divisible by 8 must raise ValueError
    with pytest.raises(ValueError, match='multiple of 8'):
        create_secure_key(bits=255)
    with pytest.raises(ValueError, match='multiple of 8'):
        create_secure_key(bits=100)


def test_create_key():
    key = create_key(keyLength=15, mode='alphaNum')
    assert len(key) == 15
    assert key.isalnum()

    key = create_key(keyLength=10, mode='numbers')
    assert len(key) == 10
    assert key.isdigit()

    key = create_key(keyLength=10, mode='lowerChars')
    assert len(key) == 10
    assert key.islower()
    assert key.isalpha()

    key = create_key(keyLength=10, mode='upperChars')
    assert len(key) == 10
    assert key.isupper()
    assert key.isalpha()

    key = create_key(keyLength=10, mode='alphaNumLower')
    assert len(key) == 10
    assert key == key.lower()

    key = create_key(keyLength=10, mode='alphaNumUpper')
    assert len(key) == 10
    assert key == key.upper()

    key = create_key(keyLength=20, mode='all')
    assert len(key) == 20


def test_check_password_security():
    errors = check_password_security('SecurePass1!')
    assert errors == []

    errors = check_password_security('short', length=8)
    assert any('minimum password length' in e for e in errors)

    errors = check_password_security('abcdefgh', check_number=True)
    assert any('digit' in e for e in errors)

    errors = check_password_security('abcdefgh', check_capital=True)
    assert any('uppercase' in e for e in errors)

    errors = check_password_security('passwörd', check_ascii=True)
    assert any('ASCII' in e for e in errors)

    errors = check_password_security('abcdefgh')
    assert errors == []

    errors = check_password_security('Abcd1234', check_number=True, check_capital=True)
    assert errors == []

    # check_nonalphanum: password without special character should fail
    errors = check_password_security('Abcd1234', check_nonalphanum=True)
    assert any('non alpha-numeric' in e for e in errors)

    # check_nonalphanum: password with special character should pass
    errors = check_password_security('Abcd123!', check_nonalphanum=True)
    assert not any('non alpha-numeric' in e for e in errors)
