"""Views."""

from django.contrib.auth.decorators import permission_required, user_passes_test
from django.shortcuts import get_object_or_404, redirect, render
from django.views.decorators.cache import cache_page

from allianceauth.services.hooks import get_extension_logger

from corphandouts.models import DoctrineReport, FittingReport, FittingToCorrect
from corphandouts.utils import (
    get_user_alliances,
    get_user_corporations,
    user_can_access_view,
    user_has_citadel_fitting_access,
)

logger = get_extension_logger(__name__)


def add_common_context(context: dict = None) -> dict:
    """Enhance the templates context with context that should be added to every page"""
    if context is None:
        context = {}

    if basic_title := context.get("page_title"):
        context["page_title"] = f"{basic_title} - Corporation Handouts"
    else:
        context["page_title"] = "Corporation Handouts"

    return context


def has_citadel_fittings_access(function=None, login_url=None):
    """check if the user has the required permissions to access the citadel application"""
    decorator = user_passes_test(user_has_citadel_fitting_access, login_url=login_url)
    if function:
        return decorator(function)
    return decorator


@permission_required("corphandouts.basic_access")
def handout_index(request):
    """Render index view."""
    doctrines = DoctrineReport.objects.filter(
        corporation_hangar_division__gt=0
    )  # Exclude in space citadels
    return render(
        request,
        "corphandouts/index.html",
        add_common_context(
            {
                "doctrines": doctrines,
            }
        ),
    )


@has_citadel_fittings_access
def citadel_index(request):
    """Render citadel index view"""
    doctrines = DoctrineReport.objects.filter(
        corporation_hangar_division=0
    )  # Excludes ship assets

    if not request.user.has_perm("corphandouts.manager"):
        if request.user.has_perm("corphandouts.alliance_view"):
            user_alliances = get_user_alliances(request.user)
            doctrines.filter(corporation__corporation__alliance__in=user_alliances)
        elif request.user.has_perm("corphandouts.corporation_view"):
            user_corporations = get_user_corporations(request.user)
            doctrines.filter(corporation__corporation__in=user_corporations)
        else:
            raise AssertionError(
                f"Unexpected branch met in citadel view with user id {request.user.id}"
            )

    return render(
        request,
        "corphandouts/index.html",
        add_common_context(
            {
                "doctrines": doctrines,
                "direct_to_structures": True,
            }
        ),
    )


def doctrine_fitting_reports(request, doctrine_id: int):
    """Shows all fitting reports for this doctrine"""
    logger.info("Trying to show fitting reports for doctrine id %d", doctrine_id)
    doctrine_report = get_object_or_404(DoctrineReport, pk=doctrine_id)

    if not user_can_access_view(request.user, doctrine_report):
        return redirect("corphandouts:index")

    fitting_reports_list = doctrine_report.fittings.all()
    logger.debug(fitting_reports_list)

    return render(
        request,
        "corphandouts/doctrine.html",
        add_common_context(
            {
                "doctrine_report": doctrine_report,
                "fitting_reports": fitting_reports_list,
                "direct_to_structures": doctrine_report.corporation_hangar_division
                == 0,
            }
        ),
    )


def show_all_bad_fits_for_doctrine(request, doctrine_id: int):
    """Shows all fittings with errors for this doctrine"""
    logger.info("Trying to show all fitting errors for doctrine id %d", doctrine_id)
    doctrine_report = get_object_or_404(DoctrineReport, pk=doctrine_id)
    logger.debug(doctrine_report)

    if not user_can_access_view(request.user, doctrine_report):
        return redirect("corphandouts:index")

    fittings = []
    for fitting_report in doctrine_report.fittings.all():
        fittings.extend(fitting_report.fits_to_correct.all())
    logger.debug(fittings)

    return render(
        request,
        "corphandouts/fittings.html",
        add_common_context(
            {
                "doctrine_id": doctrine_id,
                "fittings": fittings,
                "direct_to_structures": doctrine_report.corporation_hangar_division
                == 0,
            }
        ),
    )


def fitting_report_view(request, doctrine_id: int, fitting_report_id: int):
    """Displays a report about a specific fitting of a doctrine"""
    fitting_report = get_object_or_404(
        FittingReport, doctrine_id=doctrine_id, pk=fitting_report_id
    )
    logger.info("Displaying information on fitting repport id %d", fitting_report.id)

    if not user_can_access_view(request.user, fitting_report.doctrine):
        return redirect("corphandouts:index")

    fittings = fitting_report.fits_to_correct.all()
    logger.debug(fittings)

    return render(
        request,
        "corphandouts/fittings.html",
        add_common_context(
            {
                "doctrine_id": doctrine_id,
                "fittings": fittings,
                "direct_to_structures": fitting_report.doctrine.corporation_hangar_division
                == 0,
            },
        ),
    )


def fitting(request, fitting_id: int):
    """Fitting report"""
    fitting_to_correct = get_object_or_404(FittingToCorrect, pk=fitting_id)

    if not user_can_access_view(request.user, fitting_to_correct.fit.doctrine):
        return redirect("corphandouts:index")

    context = {
        "fitting": fitting_to_correct,
    }

    logger.info(fitting_id)

    if request.GET.get("new_page"):
        context["title"] = "title"
        context["content_file"] = "corphandouts/partials/fit_corrections.html"
        return render(
            request,
            "corphandouts/modals/generic_modal_page.html",
            add_common_context(context),
        )
    return render(
        request, "corphandouts/modals/fit_corrections.html", add_common_context(context)
    )


@cache_page(3600)
def modal_loader_body(request):
    """Draw the loader body. Useful for showing a spinner while loading a modal."""
    return render(request, "corphandouts/modals/loader_body.html")
