#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import os
import random
import string
from collections import UserDict
from random import randrange
from types import SimpleNamespace

import boto3
import pytest
import requests
import sendgrid
import slack_sdk

import iobot.testing as testing
from psi_logger import Logger


class MockSLater(UserDict):

    def __init__(self, *args, **kwargs):
        self.data = {}
        self._creds = {'access_token': ''}
        self._log = {}
        self._secrets = {}
        self.client = {}
        self.slater = {}
        self.slack_element_type_map = {}

        for key, value in kwargs.items():
            self.__setitem__(key, value)

    def __getitem__(self, key):
        return self.data.get(key)

    def __setitem__(self, key, value):
        if key in self:
            del self[key]
        self.data[key] = value

    def GetLOBByID(self, id: str):
        return MockSLater(**{'governance_lob_name': 'Assessments', 'lob_id': 1})

    def GetTowerByID(self, id: str):
        return MockSLater(**{'tower_name': 'Assessments', 'tower_id': 1})


def get_log_name(length: int = 8) -> str:
    """Get the name of the test currently being executed by pytest to use as
    the logger name for test log output.

    This method loops through all of the tests currently loaded by pytest and
    checks if the `add_imports` fixture has been passed to the doctest to
    determine if the test has been run or not. If not, return the test's name.

    If the currently running test can't be determined, fall back to a random 8
    character a-z string

    Parameters
    ==========
    length : int
        The length of the random name to generate if the test name can't be found
        Defaults to 8

    Returns
    =======
    str
        a doctest item, like:
        '<DoctestItem slater.views.SLaterAccountEditView>',
        or a random string like:
        'vymqqgom'
    """
    result: str = ""
    tests = globals()['__loader__'].__dict__['session'].__dict__.get('items')

    for test in tests:
        if test.__dict__.get('funcargs') and "add_imports" not in test.__dict__.get('funcargs', {}).keys():
            result = test.__dict__['keywords'].__dict__['node'].__repr__()
            break

    if not result:
        result = "".join([chr(randrange(97, 122)) for _ in range(length)])
    return result

class MockSlack:
    def __call__(self, **kwargs):
        if not kwargs:
            return
        v = []
        for x in kwargs.values():
            v.append(x)
        print(''.join(str(v)))
    
    def views_update(self,view_id: str,hash: str,view: str):
        x = {'view_id':view_id, 'hash': hash, 'view': view}
        if 'blocks' in x['view']:
            print(1)
        

@pytest.fixture(autouse=True)
def add_imports(doctest_namespace):
    doctest_namespace["os"] = os
    doctest_namespace["boto3"] = boto3
    doctest_namespace["requests"] = requests
    doctest_namespace["boto_session"] = boto3.session.Session()
    doctest_namespace["http_session"] = requests.Session()
    doctest_namespace["json"] = json
    doctest_namespace["log"] = Logger(get_log_name()).getLogger()
    doctest_namespace["mark"] = pytest.mark
    doctest_namespace["MockSLater"] = MockSLater
    doctest_namespace["MockSlack"] = MockSlack
    doctest_namespace["random"] = random
    doctest_namespace["sendgrid"] = sendgrid
    doctest_namespace["SimpleNamespace"] = SimpleNamespace
    doctest_namespace["slack_sdk"] = slack_sdk
    doctest_namespace["skip"] = pytest.skip
    doctest_namespace["string"] = string
    doctest_namespace["testing"] = testing
    doctest_namespace["test_config"] = testing.get_unittest_config(
        env=dict(os.environ))


def pytest_runtest_setup(item):
    # called for running each test in 'iobot' directory
    print(f"setting up {item}")
