"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 09.08.21

"""
from django.db.models import Sum
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpRequest, Http404
from django.shortcuts import render, get_object_or_404

from compensation.forms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm
from compensation.models import EcoAccount
from compensation.tables import EcoAccountTable
from intervention.forms import NewWithdrawForm
from konova.contexts import BaseContext
from konova.decorators import any_group_check, default_group_required, conservation_office_group_required
from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm, RecordForm
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.utils.user_checks import in_group


@login_required
@any_group_check
def index_view(request: HttpRequest):
    """
    Renders the index view for eco accounts

    Args:
        request (HttpRequest): The incoming request

    Returns:
        A rendered view
    """
    template = "generic_index.html"
    user = request.user
    eco_accounts = EcoAccount.objects.filter(
        deleted=None,
    )
    table = EcoAccountTable(
        request=request,
        queryset=eco_accounts
    )
    context = {
        "table": table,
    }
    context = BaseContext(request, context).context
    return render(request, template, context)


@login_required
@default_group_required
def new_view(request: HttpRequest):
    # ToDo
    pass


@login_required
@default_group_required
def edit_view(request: HttpRequest, id: str):
    # ToDo
    pass


@login_required
@any_group_check
def open_view(request: HttpRequest, id: str):
    """ Renders a detail view for a compensation

    Args:
        request (HttpRequest): The incoming request
        id (str): The compensation's id

    Returns:

    """
    template = "compensation/detail/eco_account/view.html"
    acc = get_object_or_404(EcoAccount, id=id)
    geom_form = SimpleGeomForm(instance=acc)
    _user = request.user
    is_data_shared = acc.is_shared_with(_user)

    # Order states according to surface
    before_states = acc.before_states.all().order_by("-surface")
    after_states = acc.after_states.all().order_by("-surface")

    # Precalculate logical errors between before- and after-states
    # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
    sum_before_states = before_states.aggregate(Sum("surface"))["surface__sum"] or 0
    sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0
    diff_states = abs(sum_before_states - sum_after_states)

    # Calculate rest of available surface for withdraws
    available = acc.get_available_rest(as_percentage=True)

    context = {
        "obj": acc,
        "geom_form": geom_form,
        "has_access": is_data_shared,
        "before_states": before_states,
        "after_states": after_states,
        "sum_before_states": sum_before_states,
        "sum_after_states": sum_after_states,
        "diff_states": diff_states,
        "available": available,
        "is_default_member": in_group(_user, DEFAULT_GROUP),
        "is_zb_member": in_group(_user, ZB_GROUP),
        "is_ets_member": in_group(_user, ETS_GROUP),
        "LANIS_LINK": acc.get_LANIS_link(),
    }
    context = BaseContext(request, context).context
    return render(request, template, context)


@login_required
def remove_view(request: HttpRequest, id: str):
    """ Renders a modal view for removing the eco account

    Args:
        request (HttpRequest): The incoming request
        id (str): The account's id

    Returns:

    """
    acc = get_object_or_404(EcoAccount, id=id)
    form = RemoveModalForm(request.POST or None, instance=acc, user=request.user)
    return form.process_request(
        request=request,
        msg_success=_("Eco-account removed"),
        redirect_url=reverse("compensation:acc-index"),
    )


@login_required
@default_group_required
def withdraw_remove_view(request: HttpRequest, id: str, withdraw_id: str):
    """ Renders a modal view for removing withdraws

    Args:
        request (HttpRequest): The incoming request
        id (str): The eco account's id
        withdraw_id (str): The withdraw's id

    Returns:

    """
    acc = get_object_or_404(EcoAccount, id=id)
    try:
        eco_withdraw = acc.withdraws.get(id=withdraw_id)
    except ObjectDoesNotExist:
        raise Http404("Unknown withdraw")

    form = RemoveModalForm(request.POST or None, instance=eco_withdraw, user=request.user)
    return form.process_request(
        request=request,
        msg_success=_("Withdraw removed")
    )


@login_required
@default_group_required
def log_view(request: HttpRequest, id: str):
    """ Renders a log view using modal

    Args:
        request (HttpRequest): The incoming request
        id (str): The eco acount's id

    Returns:

    """
    comp = get_object_or_404(EcoAccount, id=id)
    template = "modal/modal_generic.html"
    body_template = "log.html"

    context = {
        "modal_body_template": body_template,
        "log": comp.log.all(),
        "modal_title": _("Log"),
    }
    context = BaseContext(request, context).context
    return render(request, template, context)


@login_required
@conservation_office_group_required
def record_view(request: HttpRequest, id:str):
    """ Renders a modal form for recording an eco account

    Args:
        request (HttpRequest): The incoming request
        id (str): The account's id

    Returns:

    """
    acc = get_object_or_404(EcoAccount, id=id)
    form = RecordForm(request.POST or None, instance=acc, user=request.user)
    msg_succ = _("{} unrecorded") if acc.recorded else _("{} recorded")
    msg_succ = msg_succ.format(acc.identifier)
    return form.process_request(
        request,
        msg_succ
    )


@login_required
def state_new_view(request: HttpRequest, id: str):
    """ Renders a form for adding new states for an eco account

    Args:
        request (HttpRequest): The incoming request
        id (str): The account's id to which the new state will be related

    Returns:

    """
    acc = get_object_or_404(EcoAccount, id=id)
    form = NewStateModalForm(request.POST or None, instance=acc, user=request.user)
    return form.process_request(
        request,
        msg_success=_("State added")
    )


@login_required
def action_new_view(request: HttpRequest, id: str):
    """ Renders a form for adding new actions for an eco account

    Args:
        request (HttpRequest): The incoming request
        id (str): The account's id to which the new state will be related

    Returns:

    """
    acc = get_object_or_404(EcoAccount, id=id)
    form = NewActionModalForm(request.POST or None, instance=acc, user=request.user)
    return form.process_request(
        request,
        msg_success=_("Action added")
    )


@login_required
def deadline_new_view(request: HttpRequest, id: str):
    """ Renders a form for adding new states for an eco account

    Args:
        request (HttpRequest): The incoming request
        id (str): The account's id to which the new state will be related

    Returns:

    """
    acc = get_object_or_404(EcoAccount, id=id)
    form = NewDeadlineModalForm(request.POST or None, instance=acc, user=request.user)
    return form.process_request(
        request,
        msg_success=_("Deadline added")
    )


@login_required
def new_document_view(request: HttpRequest, id: str):
    """ Renders a form for uploading new documents

    Args:
        request (HttpRequest): The incoming request
        id (str): The account's id to which the new document will be related
    Returns:

    """
    acc = get_object_or_404(EcoAccount, id=id)
    form = NewDocumentForm(request.POST or None, request.FILES or None, instance=acc, user=request.user)
    return form.process_request(
        request,
        msg_success=_("Document added")
    )


@login_required
@default_group_required
def new_withdraw_view(request: HttpRequest, id: str):
    """ Renders a modal form view for creating withdraws

    Args:
        request ():
        id ():

    Returns:

    """
    acc = get_object_or_404(EcoAccount, id=id)
    form = NewWithdrawForm(request.POST or None, instance=acc, user=request.user)
    return form.process_request(
        request,
        msg_success=_("Withdraw added")
    )