"""
Функционал работы администратора Zendesk.
"""

from typing import Optional, Dict, List

from zenpy import Zenpy
from zenpy.lib.api_objects import User as ZenpyUser, Group as ZenpyGroup, Ticket as ZenpyTicket
from zenpy.lib.exception import APIException

from access_controller.settings import ACTRL_ZENDESK_SUBDOMAIN, ACTRL_API_EMAIL, ACTRL_API_TOKEN,  \
    ZENDESK_GROUPS, SOLVED_TICKETS_EMAIL #ACTRL_API_PASSWORD,


class ZendeskAdmin:
    """
    Класс **ZendeskAdmin** содержит описание всего функционала администратора.

    :param credentials:  Полномочия (первым указывается учетная запись организации в Zendesk)
    :type credentials: :class:`Dict[str, str]`
    :param admin:  Администратор
    :type admin: :class:`Zenpy`
    :param buffer_group_id: ID буферной группы
    :type buffer_group_id: :class:`int`
    :param solved_tickets_user_id: ID пользователя, который решил тикет
    :type solved_tickets_user_id: :class:`int`
    """

    def __init__(self, credentials: Dict[str, str]):
        self.credentials = credentials
        self.admin = self.create_admin()
        self.buffer_group_id= self.get_group(ZENDESK_GROUPS['buffer']).id
        self.solved_tickets_user_id = self.get_user(SOLVED_TICKETS_EMAIL).id

    def update_user(self, user: ZenpyUser) -> None:
        """
        Функция сохраняет изменение пользователя в Zendesk.

        :param user: Пользователь с изменёнными данными
        """
        self.admin.users.update(user)

    def update_tickets(self, tickets: List[ZenpyTicket]) -> None:
        """
        Функция сохраняет изменение тикетов в Zendesk.

        :param tickets: Тикеты с изменёнными данными
        """
        if tickets:
            self.admin.tickets.update(tickets)

    def check_user(self, email: str) -> bool:
        """
        Функция осуществляет проверку существования пользователя в Zendesk по email.

        :param email: Email пользователя
        :return: Является ли зарегистрированным
        """
        return bool(self.admin.search(email, type='user'))

    def get_user(self, email: str) -> ZenpyUser:
        """
        Функция возвращает пользователя (объект) по его email.

        :param email: Email пользователя
        :return: Объект пользователя, найденного в БД
        """
        return self.admin.users.search(email).values[0]

    def get_group(self, name: str) -> Optional[ZenpyGroup]:
        """
        Функция возвращает группу по названию

        :param name: Имя пользователя
        :return: Группы пользователя (в случае отсутствия None)
        """
        groups = self.admin.search(name, type='group')
        for group in groups:
            return group
        return None

    def get_user_org(self, email: str) -> Optional[str]:
        """
        Функция возвращает организацию, к которой относится пользователь по его email.

        :param email: Email пользователя
        :return: Организация пользователя
        """
        user = self.admin.users.search(email).values[0]
        return user.organization.name if user.organization else None

    def create_admin(self) -> Zenpy:
        """
        Функция создает администратора, проверяя наличие вводимых данных в env.

        :raise: :class:`ValueError`: исключение, вызываемое если email не введен в env
        :raise: :class:`APIException`: исключение, вызываемое если пользователя с таким email не существует в Zendesk
        """
        if self.credentials.get('email') is None:
            raise ValueError('access_controller email not in env')

        if self.credentials.get('token') is None and self.credentials.get('password') is None:
            raise ValueError('access_controller token or password not in env')

        admin = Zenpy(**self.credentials)
        try:
            admin.search(self.credentials['email'], type='user')
        except APIException as invalid_data:
            raise ValueError('invalid access_controller`s login data') from invalid_data
        return admin


zenpy = ZendeskAdmin({
    'subdomain': ACTRL_ZENDESK_SUBDOMAIN,
    'email': ACTRL_API_EMAIL,
    'token': ACTRL_API_TOKEN,
    #'password': ACTRL_API_PASSWORD,
})
