"""
Django views for interacting with Stock app
"""

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from datetime import datetime

from django.views.generic import DetailView, ListView
from django.urls import reverse
from django.http import HttpResponseRedirect

from django.utils.translation import gettext_lazy as _

from InvenTree.views import AjaxUpdateView, AjaxDeleteView, AjaxCreateView
from InvenTree.views import QRCodeView
from InvenTree.views import InvenTreeRoleMixin
from InvenTree.forms import ConfirmForm

from InvenTree.helpers import str2bool

from .models import StockItem, StockLocation, StockItemTracking

import common.settings

from . import forms as StockForms

from plugin.views import InvenTreePluginViewMixin


class StockIndex(InvenTreeRoleMixin, InvenTreePluginViewMixin, ListView):
    """ StockIndex view loads all StockLocation and StockItem object
    """
    model = StockItem
    template_name = 'stock/location.html'
    context_obect_name = 'locations'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs).copy()

        # Return all top-level locations
        locations = StockLocation.objects.filter(parent=None)

        context['locations'] = locations
        context['items'] = StockItem.objects.all()

        context['loc_count'] = StockLocation.objects.count()
        context['stock_count'] = StockItem.objects.count()

        # No 'ownership' checks are necessary for the top-level StockLocation view
        context['user_owns_location'] = True
        context['location_owner'] = None
        context['ownership_enabled'] = common.models.InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')

        return context


class StockLocationDetail(InvenTreeRoleMixin, InvenTreePluginViewMixin, DetailView):
    """
    Detailed view of a single StockLocation object
    """

    context_object_name = 'location'
    template_name = 'stock/location.html'
    queryset = StockLocation.objects.all()
    model = StockLocation

    def get_context_data(self, **kwargs):

        context = super().get_context_data(**kwargs)

        context['ownership_enabled'] = common.models.InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
        context['location_owner'] = context['location'].get_location_owner()
        context['user_owns_location'] = context['location'].check_ownership(self.request.user)

        return context


class StockItemDetail(InvenTreeRoleMixin, InvenTreePluginViewMixin, DetailView):
    """
    Detailed view of a single StockItem object
    """

    context_object_name = 'item'
    template_name = 'stock/item.html'
    queryset = StockItem.objects.all()
    model = StockItem

    def get_context_data(self, **kwargs):
        """
        Add information on the "next" and "previous" StockItem objects,
        based on the serial numbers.
        """

        data = super().get_context_data(**kwargs)

        if self.object.serialized:
            data['previous'] = self.object.get_next_serialized_item(reverse=True)
            data['next'] = self.object.get_next_serialized_item()

        data['ownership_enabled'] = common.models.InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
        data['item_owner'] = self.object.get_item_owner()
        data['user_owns_item'] = self.object.check_ownership(self.request.user)

        return data

    def get(self, request, *args, **kwargs):
        """ check if item exists else return to stock index """

        stock_pk = kwargs.get('pk', None)

        if stock_pk:
            try:
                stock_item = StockItem.objects.get(pk=stock_pk)
            except StockItem.DoesNotExist:
                stock_item = None

            if not stock_item:
                return HttpResponseRedirect(reverse('stock-index'))

        return super().get(request, *args, **kwargs)


class StockLocationQRCode(QRCodeView):
    """ View for displaying a QR code for a StockLocation object """

    ajax_form_title = _("Stock Location QR code")

    role_required = ['stock_location.view', 'stock.view']

    def get_qr_data(self):
        """ Generate QR code data for the StockLocation """
        try:
            loc = StockLocation.objects.get(id=self.pk)
            return loc.format_barcode()
        except StockLocation.DoesNotExist:
            return None


class StockItemReturnToStock(AjaxUpdateView):
    """
    View for returning a stock item (which is assigned to a customer) to stock.
    """

    model = StockItem
    ajax_form_title = _("Return to Stock")
    context_object_name = "item"
    form_class = StockForms.ReturnStockItemForm

    def validate(self, item, form, **kwargs):

        location = form.cleaned_data.get('location', None)

        if not location:
            form.add_error('location', _('Specify a valid location'))

    def save(self, item, form, **kwargs):

        location = form.cleaned_data.get('location', None)

        if location:
            item.returnFromCustomer(location, self.request.user)

    def get_data(self):
        return {
            'success': _('Stock item returned from customer')
        }


class StockItemDeleteTestData(AjaxUpdateView):
    """
    View for deleting all test data
    """

    model = StockItem
    form_class = ConfirmForm
    ajax_form_title = _("Delete All Test Data")

    role_required = ['stock.change', 'stock.delete']

    def get_form(self):
        return ConfirmForm()

    def post(self, request, *args, **kwargs):

        valid = False

        stock_item = StockItem.objects.get(pk=self.kwargs['pk'])
        form = self.get_form()

        confirm = str2bool(request.POST.get('confirm', False))

        if confirm is not True:
            form.add_error('confirm', _('Confirm test data deletion'))
            form.add_error(None, _('Check the confirmation box'))
        else:
            stock_item.test_results.all().delete()
            valid = True

        data = {
            'form_valid': valid,
        }

        return self.renderJsonResponse(request, form, data)


class StockItemQRCode(QRCodeView):
    """ View for displaying a QR code for a StockItem object """

    ajax_form_title = _("Stock Item QR Code")
    role_required = 'stock.view'

    def get_qr_data(self):
        """ Generate QR code data for the StockItem """
        try:
            item = StockItem.objects.get(id=self.pk)
            return item.format_barcode()
        except StockItem.DoesNotExist:
            return None


class StockItemConvert(AjaxUpdateView):
    """
    View for 'converting' a StockItem to a variant of its current part.
    """

    model = StockItem
    form_class = StockForms.ConvertStockItemForm
    ajax_form_title = _('Convert Stock Item')
    ajax_template_name = 'stock/stockitem_convert.html'
    context_object_name = 'item'

    def get_form(self):
        """
        Filter the available parts.
        """

        form = super().get_form()
        item = self.get_object()

        form.fields['part'].queryset = item.part.get_conversion_options()

        return form

    def save(self, obj, form):

        stock_item = self.get_object()

        variant = form.cleaned_data.get('part', None)

        stock_item.convert_to_variant(variant, user=self.request.user)

        return stock_item


class StockLocationDelete(AjaxDeleteView):
    """
    View to delete a StockLocation
    Presents a deletion confirmation form to the user
    """

    model = StockLocation
    success_url = '/stock'
    ajax_template_name = 'stock/location_delete.html'
    context_object_name = 'location'
    ajax_form_title = _('Delete Stock Location')


class StockItemDelete(AjaxDeleteView):
    """
    View to delete a StockItem
    Presents a deletion confirmation form to the user
    """

    model = StockItem
    success_url = '/stock/'
    ajax_template_name = 'stock/item_delete.html'
    context_object_name = 'item'
    ajax_form_title = _('Delete Stock Item')


class StockItemTrackingDelete(AjaxDeleteView):
    """
    View to delete a StockItemTracking object
    Presents a deletion confirmation form to the user
    """

    model = StockItemTracking
    ajax_template_name = 'stock/tracking_delete.html'
    ajax_form_title = _('Delete Stock Tracking Entry')


class StockItemTrackingEdit(AjaxUpdateView):
    """ View for editing a StockItemTracking object """

    model = StockItemTracking
    ajax_form_title = _('Edit Stock Tracking Entry')
    form_class = StockForms.TrackingEntryForm


class StockItemTrackingCreate(AjaxCreateView):
    """ View for creating a new StockItemTracking object.
    """

    model = StockItemTracking
    ajax_form_title = _("Add Stock Tracking Entry")
    form_class = StockForms.TrackingEntryForm

    def post(self, request, *args, **kwargs):

        self.request = request
        self.form = self.get_form()

        valid = False

        if self.form.is_valid():
            stock_id = self.kwargs['pk']

            if stock_id:
                try:
                    stock_item = StockItem.objects.get(id=stock_id)

                    # Save new tracking information
                    tracking = self.form.save(commit=False)
                    tracking.item = stock_item
                    tracking.user = self.request.user
                    tracking.quantity = stock_item.quantity
                    tracking.date = datetime.now().date()
                    tracking.system = False

                    tracking.save()

                    valid = True

                except (StockItem.DoesNotExist, ValueError):
                    pass

        data = {
            'form_valid': valid
        }

        return self.renderJsonResponse(request, self.form, data=data)
