"""
Utilities
"""

from django.core.handlers.wsgi import WSGIRequest
from django.utils.functional import lazy
from django.utils.html import format_html

from allianceauth.authentication.admin import User
from allianceauth.eveonline.models import (
    EveAllianceInfo,
    EveCharacter,
    EveCorporationInfo,
)

from afat.providers import esi

# Format for output of datetime for this app
DATETIME_FORMAT = "%Y-%m-%d %H:%M"

format_html_lazy = lazy(format_html, str)


class NoDataError(Exception):
    """
    NoDataError
    """

    def __init__(self, msg):
        Exception.__init__(self, msg)


def write_log(request: WSGIRequest, log_event: str, fatlink_hash: str, log_text: str):
    """
    Write the log
    :param request:
    :type request:
    :param log_event:
    :type log_event:
    :param fatlink_hash:
    :type fatlink_hash:
    :param log_text:
    :type log_text:
    :return:
    :rtype:
    """

    from afat.models import AFatLog

    afat_log = AFatLog()
    afat_log.user = request.user
    afat_log.log_event = log_event
    afat_log.log_text = log_text
    afat_log.fatlink_hash = fatlink_hash
    afat_log.save()


def get_or_create_character(name: str = None, character_id: int = None):
    """
    This function takes a name or id of a character and checks
    to see if the character already exists.
    If the character does not already exist, it will create the
    character object, and if needed the corp/alliance objects as well.
    :param name:
    :type name:
    :param character_id:
    :type character_id:
    :return:
    :rtype:
    """

    eve_character = None

    if name:
        # If a name is passed to this function, we have to check it on ESI
        result = esi.client.Search.get_search(
            categories=["character"], search=name, strict=True
        ).result()

        if "character" not in result:
            return None

        character_id = result["character"][0]
        eve_character = EveCharacter.objects.filter(character_id=character_id)
    elif character_id:
        # If an ID is passed to this function, we can just check the db for it.
        eve_character = EveCharacter.objects.filter(character_id=character_id)
    elif not name and not character_id:
        raise NoDataError("No character name or character id provided.")

    if eve_character is not None and len(eve_character) == 0:
        # Create character
        character = EveCharacter.objects.create_character(character_id)
        character = EveCharacter.objects.get(pk=character.pk)

        # Make corp and alliance info objects for future sane
        if character.alliance_id is not None:
            test = EveAllianceInfo.objects.filter(alliance_id=character.alliance_id)

            if len(test) == 0:
                EveAllianceInfo.objects.create_alliance(character.alliance_id)
        else:
            test = EveCorporationInfo.objects.filter(
                corporation_id=character.corporation_id
            )

            if len(test) == 0:
                EveCorporationInfo.objects.create_corporation(character.corporation_id)

    else:
        character = eve_character[0]

    return character


def get_or_create_corporation_info(corporation_id: int) -> EveCorporationInfo:
    """
    Get or create corporation info
    :param corporation_id:
    :type corporation_id:
    :return:
    :rtype:
    """

    try:
        eve_corporation_info = EveCorporationInfo.objects.get(
            corporation_id=corporation_id
        )
    except EveCorporationInfo.DoesNotExist:
        eve_corporation_info = EveCorporationInfo.objects.create_corporation(
            corp_id=corporation_id
        )

    return eve_corporation_info


def get_or_create_alliance_info(alliance_id: int) -> EveAllianceInfo:
    """
    Get or create alliance info
    :param alliance_id:
    :type alliance_id:
    :return:
    :rtype:
    """

    try:
        eve_alliance_info = EveAllianceInfo.objects.get(alliance_id=alliance_id)
    except EveAllianceInfo.DoesNotExist:
        eve_alliance_info = EveAllianceInfo.objects.create_alliance(
            alliance_id=alliance_id
        )

    return eve_alliance_info


def get_main_character_from_user(user: User) -> str:
    """
    Get the main character from a user
    :param user:
    :type user:
    :return:
    :rtype:
    """

    user_main_character = user.username

    try:
        user_profile = user.profile
        user_main_character = user_profile.main_character.character_name
    except AttributeError:
        pass

    return user_main_character
