import random
import string
from unittest import mock

from django.test import SimpleTestCase

from ...utils.logging import (TAG_DATA_FEED, TAG_PERF, get_logger,
                              get_logger_name)
from .samples import MyClass, my_func


class LoggingTest(SimpleTestCase):

    def test_get_logger_name(self):
        module_name = __name__
        ext_module_name = my_func.__module__

        MainType = MyClass
        main_type = MainType(11)
        main_type_logger = f'{ext_module_name}.{MainType.__qualname__}'
        SubType = MyClass.MySubClass
        sub_type = SubType(13)
        sub_type_logger = f'{ext_module_name}.{SubType.__qualname__}'

        def local_func(a: int, b: int):
            return a + b

        # None
        self.assertIsNone(get_logger_name())
        self.assertIsNone(get_logger_name(None))

        # classes natives
        self.assertIsNone(get_logger_name(str))
        self.assertIsNone(get_logger_name(int))
        self.assertIsNone(get_logger_name(dict))
        self.assertIsNone(get_logger_name(list))
        self.assertIsNone(get_logger_name(tuple))

        # instances de classes natives (mais pas str)
        self.assertIsNone(get_logger_name(1))
        self.assertIsNone(get_logger_name({'a': 'b'}))
        self.assertIsNone(get_logger_name(['c']))
        self.assertIsNone(get_logger_name(('d',)))

        # fonctions natives
        self.assertIsNone(get_logger_name(str.join))

        # str
        self.assertEqual(get_logger_name('test'), 'test')
        self.assertEqual(get_logger_name(''), None)

        # classes
        self.assertEqual(get_logger_name(MainType), main_type_logger)
        self.assertEqual(get_logger_name(SubType), sub_type_logger)

        # instances de classes
        self.assertEqual(get_logger_name(main_type), main_type_logger)
        self.assertEqual(get_logger_name(sub_type), sub_type_logger)

        # fonctions et méthodes
        self.assertEqual(get_logger_name(local_func), module_name)
        self.assertEqual(get_logger_name(my_func), ext_module_name)
        self.assertEqual(get_logger_name(MainType.class_met), main_type_logger)
        self.assertEqual(get_logger_name(MainType.static_met), main_type_logger)
        self.assertEqual(get_logger_name(main_type.std_met), main_type_logger)
        self.assertEqual(get_logger_name(SubType.sub_class_met), sub_type_logger)
        self.assertEqual(get_logger_name(SubType.sub_static_met), sub_type_logger)
        self.assertEqual(get_logger_name(sub_type.sub_std_met), sub_type_logger)

    def test_get_logger_without_tags(self):
        func_1 = MyClass.class_met
        func_2 = MyClass.static_met

        def given():
            self.assertEqual(get_logger_name(func_1), get_logger_name(func_2), 'le nom de logger doit être le même')
        given()

        msg = "l'instance doit être la même"
        logger_name = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
        self.assertIs(get_logger(logger_name), get_logger(logger_name), msg)
        self.assertIs(get_logger(func_1), get_logger(func_2), msg)

    def test_get_logger_with_tags(self):
        func_1 = MyClass.class_met
        func_2 = MyClass.static_met

        def given():
            self.assertEqual(get_logger_name(func_1), get_logger_name(func_2), 'le nom de logger doit être le même')
        given()

        msg = "l'instance doit être la même"
        for tags in [TAG_PERF, TAG_DATA_FEED, ('1', '2'), ['3', '4'], set(['5', '6'])]:
            with self.subTest(tags=tags):
                logger_name = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
                self.assertIs(get_logger(logger_name, tags), get_logger(logger_name, tags), msg)
                self.assertIs(get_logger(func_1, tags), get_logger(func_2, tags), msg)

        prev_logger = None
        logger_name = ''.join(random.choice(string.ascii_lowercase) for i in range(10))
        for i, tags in enumerate([('1', '2', '3', '4'), ['3', '4', '1', '2'], set(['2', '1', '3', '4', '1'])]):
            curr_logger = get_logger(logger_name, tags)
            if i > 0:
                self.assertIs(curr_logger, prev_logger, msg)
            prev_logger = get_logger(logger_name, tags)
