from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.utils.translation import gettext_lazy as _
from django.http import HttpRequest
from django.shortcuts import render, get_object_or_404

from intervention.forms import NewInterventionForm, EditInterventionForm, ShareInterventionForm
from intervention.models import Intervention
from intervention.tables import InterventionTable
from konova.contexts import BaseContext
from konova.decorators import *
from konova.forms import RemoveForm, SimpleGeomForm, NewDocumentForm


@login_required
def index_view(request: HttpRequest):
    """
    Renders the index view for Interventions

    Args:
        request (HttpRequest): The incoming request

    Returns:
        A rendered view
    """
    template = "generic_index.html"

    # Filtering by user access is performed in table filter inside of InterventionTableFilter class
    interventions = Intervention.objects.filter(
        deleted_on=None,  # not deleted
        next_version=None,  # only newest versions
    ).order_by(
        "-created_on"
    )
    table = InterventionTable(
        request=request,
        queryset=interventions
    )
    context = {
        "table": table,
    }
    context = BaseContext(request, context).context
    return render(request, template, context)


@login_required
def new_view(request: HttpRequest):
    """
    Renders a view for a new intervention creation

    Args:
        request (HttpRequest): The incoming request

    Returns:

    """
    template = "konova/form.html"
    form = NewInterventionForm(request.POST or None)
    if request.method == "POST":
        if form.is_valid():
            intervention = form.save(request.user)
            messages.success(request, _("Intervention {} added").format(intervention.title))
            return redirect("intervention:index")
        else:
            messages.error(request, _("Invalid input"))
    else:
        # For clarification: nothing in this case
        pass
    context = {
        "form": form,
    }
    context = BaseContext(request, context).context
    return render(request, template, context)


@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 intervention's id to which the new document will be related
    Returns:

    """
    intervention = get_object_or_404(Intervention, id=id)
    form = NewDocumentForm(request.POST or None, request.FILES or None, instance=intervention, user=request.user)
    template = form.template
    if request.method == "POST":
        if form.is_valid():
            doc = form.save()
            messages.success(
                request,
                _("Document '{}' added").format(doc.title)
            )

            return redirect(request.META.get("HTTP_REFERER", "home"))
        else:
            messages.info(
                request,
                _("There was an error on this form.")
            )
            return redirect(request.META.get("HTTP_REFERER", "home"))
    elif request.method == "GET":
        context = {
            "form": form
        }
        context = BaseContext(request, context).context
        return render(request, template, context)
    else:
        raise NotImplementedError


@login_required
def open_view(request: HttpRequest, id: str):
    """ Renders a detail view for viewing an intervention's data

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

    Returns:

    """
    template = "intervention/detail/view.html"
    intervention = get_object_or_404(Intervention, id=id)
    has_access = intervention.has_access(user=request.user)

    geom_form = SimpleGeomForm(
        instance=intervention
    )

    context = {
        "intervention": intervention,
        "has_access": has_access,
        "geom_form": geom_form,
    }

    if not has_access:
        messages.info(request, _("Remember: This data has not been shared with you, yet. This means you can only read but can not edit or perform any actions like running a check or recording."))

    context = BaseContext(request, context).context
    return render(request, template, context)


@login_required
def edit_view(request: HttpRequest, id: str):
    """
    Renders a view for editing interventions

    Args:
        request (HttpRequest): The incoming request

    Returns:

    """
    template = "konova/form.html"
    intervention = get_object_or_404(Intervention, id=id)
    if request.method == "POST":
        form = EditInterventionForm(request.POST or None, instance=intervention)
        if form.is_valid():
            intervention = form.save(request.user)
            messages.success(request, _("{} edited").format(intervention))
            return redirect("intervention:index")
        else:
            messages.error(request, _("Invalid input"))
    form = EditInterventionForm(instance=intervention)
    context = {
        "form": form,
    }
    context = BaseContext(request, context).context
    return render(request, template, context)


@login_required
def remove_view(request: HttpRequest, id: str):
    """ Renders a remove view for this intervention

    Args:
        request (HttpRequest): The incoming request
        id (str): The uuid id as string

    Returns:

    """
    template = "konova/form.html"
    obj = Intervention.objects.get(id=id)

    # ToDo

    form = RemoveForm(
        object_to_remove=obj,
        remove_post_url=reverse("intervention:remove", args=(id,)),
        cancel_url=reverse("intervention:index"),
    )
    context = {
        "form": form,
    }
    context = BaseContext(request, context).context
    return render(request, template, context)


@login_required
def share_view(request: HttpRequest, id: str, token: str):
    """ Performs sharing of an intervention

    If token given in url is not valid, the user will be redirected to the dashboard

    Args:
        request (HttpRequest): The incoming request
        id (str): Intervention's id
        token (str): Access token for intervention

    Returns:

    """
    user = request.user
    intervention = get_object_or_404(Intervention, id=id)
    # Check tokens
    if intervention.access_token == token:
        # Send different messages in case user has already been added to list of sharing users
        if intervention.has_access(user):
            messages.info(
                request,
                _("{} has already been shared with you").format(intervention.identifier)
            )
        else:
            messages.success(
                request,
                _("{} has been shared with you").format(intervention.identifier)
            )
            intervention.users.add(user)
        return redirect("intervention:open", id=id)
    else:
        messages.error(
            request,
            _("Share link invalid"),
            extra_tags="danger",
        )
        return redirect("home")


@login_required
def create_share_view(request: HttpRequest, id: str):
    """ Renders sharing form for an intervention

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

    Returns:

    """
    user = request.user
    intervention = get_object_or_404(Intervention, id=id)
    form = ShareInterventionForm(request.POST or None, instance=intervention, request=request)
    if request.method != "GET":
        raise NotImplementedError
    context = {
        "form": form,
    }
    context = BaseContext(request, context).context
    return render(request, form.template, context)