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

import json

from django.core.serializers.json import DjangoJSONEncoder
from django.http import HttpResponse
from django.shortcuts import render_to_response, render
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import TemplateView
from django.db.models.functions import Coalesce
from django.db.models import Sum, Case, When, IntegerField, Count

from core.views import LoginRequiredMixin
from measurement.models import Size, InventoryBySize
from order_contract.models import OrderContract, ProductQuantity
from measurement.authentication_code import AuthenticationCheckMixin


class SubmissionStatusView(LoginRequiredMixin, TemplateView):
	template_name = 'measurement/stats/submission_status.html'

	def get_context_data(self, **kwargs):
		context = super(SubmissionStatusView, self).get_context_data(**kwargs)
		order = OrderContract.objects.get(id=self.kwargs['order_id'])
		kindergartener_set = order.kindergartener_set.all().order_by('create_date').distinct()

		context["kindergartener_set"] = getKindergartenerSizeSet(kindergartener_set)
		context["order"] = order
		return context


class SubmissionStatusForGuest(AuthenticationCheckMixin, TemplateView):
	template_name = 'measurement/stats/submission_status_guest.html'

	def get_context_data(self, **kwargs):
		context = super(SubmissionStatusForGuest, self).get_context_data(**kwargs)
		order = OrderContract.objects.get(id=self.kwargs['order_id'])
		kindergartener_set = order.kindergartener_set.all()

		context["kindergartener_set"] = getKindergartenerSizeSet(kindergartener_set)
		context["order"] = order
		return context


class SizeStatusView(LoginRequiredMixin, TemplateView):
	template_name = 'measurement/stats/size_status.html'

	def get_context_data(self, **kwargs):
		context = super(SizeStatusView, self).get_context_data(**kwargs)
		order = OrderContract.objects.get(id=self.kwargs['order_id'])
		couple_set = order.finalfittingset.selectedcoupleset_set.all().order_by(
				'-couple__boy_fitting__fitting_category__season',
				'couple__boy_fitting__fitting_category__style'
		)
		context["final_set"] = []
		context["size_ratio"] = []

		for set in couple_set:
			boy_fitting = set.couple.boy_fitting
			girl_fitting = set.couple.girl_fitting

			product_set = {
				set.couple.girl_fitting.fitting_category.gender: girl_fitting.product_set
					.exclude(product__product_type__name='acc').order_by('product__product_type_id'),
				set.couple.boy_fitting.fitting_category.gender: boy_fitting.product_set
					.exclude(product__product_type__name='acc').order_by('product__product_type_id')
			}
			couple_filter = {
				'kindergartener__order_contract': order,
				'season': set.couple.boy_fitting.fitting_category.season,
				'style': set.couple.boy_fitting.fitting_category.style
			}
			couple_size = aggregateSize(couple_filter)
			couple_size_percentage = percentageSizeDict(couple_size, sum(couple_size.values()))

			temp = json.dumps(dict(
				season = set.couple.boy_fitting.fitting_category.get_season_display(),
				style = set.couple.boy_fitting.fitting_category.get_style_display(),
				size = couple_size_percentage
			), cls=DjangoJSONEncoder)

			context["size_ratio"].append(temp)

			for gender, values in product_set.iteritems():
				q = {
					'kindergartener__order_contract': order,
					'season': set.couple.boy_fitting.fitting_category.season,
					'style': set.couple.boy_fitting.fitting_category.style,
					'kindergartener__gender': gender
				}
				for product in values:
					size = aggregateSize(q)
					product_size_total = sum(size.values())
					size_percentage = percentageSizeDict(size, product_size_total)

					inventory_by_size, inventory_by_size_created= InventoryBySize.objects.get_or_create(
						contract_product=ProductQuantity.objects.get(order_contract=order, main_fabric_id=product.id, gender=gender)
					)

					inventory = dict(
						size90 = inventory_by_size.size90,
						size100 = inventory_by_size.size100,
						size110 = inventory_by_size.size110,
						size120 = inventory_by_size.size120,
						size130 = inventory_by_size.size130,
						size140 = inventory_by_size.size140,
						size150 = inventory_by_size.size150
					)

					required_inventory = getRequiredInventory(size, inventory)

					temp = dict(
						product=product,
						gender = gender,
						style = set.couple.boy_fitting.fitting_category.get_style_display(),
						season = set.couple.boy_fitting.fitting_category.get_season_display(),
						size = size,
						product_size_total = product_size_total,
						size_percentage = size_percentage,
						inventory_by_size = inventory,
						total_by_product = sum(inventory.values()),
						required_inventory = required_inventory,
						required_inventory_total = sum(required_inventory.values())
					)
					context["final_set"].append(temp)

		context["order"] = order
		return context


@csrf_exempt
def inventorySubmit(request):
	order = OrderContract.objects.get(id=request.POST.get('order_id'))
	inventory_dict = json.loads(request.POST.get('inventory'))

	for item in inventory_dict:
		inventory_obj = InventoryBySize.objects.get(
			contract_product=ProductQuantity.objects.get(order_contract=order, main_fabric_id=item['product'], gender=item['gender'])
		)
		inventory_obj.size90 = item['size90']
		inventory_obj.size100 = item['size100']
		inventory_obj.size110 = item['size110']
		inventory_obj.size120 = item['size120']
		inventory_obj.size130 = item['size130']
		inventory_obj.size140 = item['size140']
		inventory_obj.size150 = item['size150']
		inventory_obj.save()

	return HttpResponse(json.dumps({'success': True}), content_type='application/json')

@csrf_exempt
def sortKindergartenerSet(request):
	order = OrderContract.objects.get(id=request.POST.get('order_id'))
	condition = request.POST.get('condition')

	sorted_set = order.kindergartener_set.all().order_by(condition)
	kindergartener_set = getKindergartenerSizeSet(sorted_set)

	return render(request, 'measurement/stats/submission_kindergartener_list.html', {
		'kindergartener_set': kindergartener_set,
		'order': order
	})


def aggregateSize(condition):
	return Size.objects.filter(**condition).aggregate(
		size90=summary_size(90),
		size100=summary_size(100),
		size110=summary_size(110),
		size120=summary_size(120),
		size130=summary_size(130),
		size140=summary_size(140),
		size150=summary_size(150)
	)

def summary_size(size):
	return (Coalesce(Count(
		Case(
			When(
				checked_size=size,
				then=1
			),
			output_field=IntegerField()
		)
	), 0))

def summary_size_percentage(count, total):
	if count == 0 or total == 0:
		return 0
	else:
		return count * 100 / total

def percentageSizeDict(aggregation_dict, totalCnt):
	return dict(
		size90 = summary_size_percentage(aggregation_dict['size90'], totalCnt),
		size100 = summary_size_percentage(aggregation_dict['size100'], totalCnt),
		size110 = summary_size_percentage(aggregation_dict['size110'], totalCnt),
		size120 = summary_size_percentage(aggregation_dict['size120'], totalCnt),
		size130 = summary_size_percentage(aggregation_dict['size130'], totalCnt),
		size140 = summary_size_percentage(aggregation_dict['size140'], totalCnt),
		size150 = summary_size_percentage(aggregation_dict['size150'], totalCnt)
	)

def getRequiredInventory(size_dict, inventory_dict):
	required_inventory = dict()
	for size_k, value in size_dict.iteritems():
		required_inventory[size_k] = value - inventory_dict[size_k]

	return required_inventory

def getKindergartenerSizeSet(kindergartener_set):
	sizeset = []
	for kindergartener in kindergartener_set:
		temp = {
			'kindergartener': kindergartener,
			'size_set': kindergartener.size_set.all().order_by('-season', 'style')
		}
		temp["kindergartener"].gender = kindergartener.get_gender_display()
		for size in temp["size_set"]:
			size.season = size.get_season_display()
			size.style = size.get_style_display()
		sizeset.append(temp)

	return sizeset