import os
import unittest
from unittest import mock

import security

KEY = 'k' * 40


class ConfiguredKey(unittest.TestCase):
    def test_missing(self):
        with mock.patch.dict(os.environ, {}, clear=True):
            with self.assertRaises(security.ApiKeyConfigError):
                security.configured_key()

    def test_blank(self):
        with mock.patch.dict(os.environ, {security.ENV_NAME: '   '}, clear=True):
            with self.assertRaises(security.ApiKeyConfigError):
                security.configured_key()

    def test_too_short(self):
        with mock.patch.dict(os.environ, {security.ENV_NAME: 'short'}, clear=True):
            with self.assertRaises(security.ApiKeyConfigError):
                security.configured_key()

    def test_valid_is_stripped(self):
        with mock.patch.dict(os.environ, {security.ENV_NAME: f'  {KEY}\n'}, clear=True):
            self.assertEqual(security.configured_key(), KEY)


class Bearer(unittest.TestCase):
    def test_extract(self):
        self.assertEqual(security.extract_bearer(f'Bearer {KEY}'), KEY)
        self.assertEqual(security.extract_bearer(f'bearer   {KEY} '), KEY)

    def test_rejects_other_schemes_and_empty(self):
        for value in (None, '', 'Bearer', 'Bearer ', f'Basic {KEY}', KEY):
            self.assertEqual(security.extract_bearer(value), '', value)


class Validation(unittest.TestCase):
    def test_match(self):
        self.assertTrue(security.is_valid(KEY, KEY))

    def test_mismatch_and_empty(self):
        self.assertFalse(security.is_valid('x' * 40, KEY))
        self.assertFalse(security.is_valid(KEY[:-1], KEY))
        self.assertFalse(security.is_valid('', KEY))
        self.assertFalse(security.is_valid(KEY, ''))

    def test_non_ascii_does_not_raise(self):
        self.assertFalse(security.is_valid('کلید-نادرست', KEY))


if __name__ == '__main__':
    unittest.main()
