import os

import reversion

from django.contrib.sites.shortcuts import get_current_site
from django.db import models
from django.db.models import Sum
from django.urls import reverse_lazy
from django.utils import timezone
from django.conf import settings

from tvorba.models import Problem, Deadline, Cislo, Uloha, aux_generate_filename
from various.models import SeminarModelBase

from odevzdavatko.utils import vzorecek_na_prepocet, inverze_vzorecku_na_prepocet
from personalni.models import Resitel

@reversion.register(ignore_duplicates=True)
class Reseni(SeminarModelBase):

	class Meta:
		db_table = 'seminar_reseni'
		verbose_name = 'Řešení'
		verbose_name_plural = 'Řešení'
		#ordering = ['-problem', 'resitele']	# FIXME: Takhle to chceme, ale nefunguje to.
		ordering = ['-cas_doruceni']

	# Interní ID
	id = models.AutoField(primary_key = True)

	# Ke každé dvojici řešní a problém existuje nanejvýš jedno hodnocení, doplnění vazby.
	problem = models.ManyToManyField(Problem, verbose_name='problém', help_text='Problém',
									 through='Hodnoceni')

	resitele = models.ManyToManyField(Resitel, verbose_name='autoři řešení',
									  help_text='Seznam autorů řešení', through='Reseni_Resitele')


	cas_doruceni = models.DateTimeField('čas_doručení', default=timezone.now, blank=True)

	FORMA_PAPIR = 'papir'
	FORMA_EMAIL = 'email'
	FORMA_UPLOAD = 'upload'
	FORMA_CHOICES = [
		(FORMA_PAPIR, 'Papírové řešení'),
		(FORMA_EMAIL, 'Emailem'),
		(FORMA_UPLOAD, 'Upload přes web'),
	]
	forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False,
							 default=FORMA_EMAIL)

	text_cely = models.OneToOneField('treenode.ReseniNode', verbose_name='Plná verze textu řešení',
									 blank=True, null=True, related_name="reseni_cely_set",
									 on_delete=models.PROTECT)

	poznamka = models.TextField('neveřejná poznámka', blank=True,
								help_text='Neveřejná poznámka k řešení (plain text)')

	zverejneno = models.BooleanField('řešení zveřejněno', default=False,
									 help_text='Udává, zda je řešení zveřejněno')

	def verejne_url(self):
		return str(reverse_lazy('odevzdavatko_detail_reseni', args=[self.id]))

	def absolute_url(self):
		return "https://" + str(get_current_site(None)) + self.verejne_url()

	def resitel_url(self):
		return f'https://{get_current_site(None)}{reverse_lazy("odevzdavatko_resitel_reseni", args=[self.id])}'

	# má OneToOneField s:
	# Konfera

	# má ForeignKey s:
	# Hodnoceni

	def sum_body(self):
		return self.hodnoceni_set.all().aggregate(Sum('body'))["body__sum"]

	def __str__(self):
		return "{}({}): {}({})".format(self.resitele.first(),len(self.resitele.all()), self.problem.first() ,len(self.problem.all()))
	# NOTE: Potenciální DB HOG (bez select_related)

	def deadline_reseni(self):
		return Deadline.objects.filter(deadline__gte=self.cas_doruceni).order_by("deadline").first()

## Pravdepodobne uz nebude potreba:
#	def save(self, *args, **kwargs):
#		if ((self.cislo_body is None) and (self.problem.cislo_reseni) and
#				(self.problem.typ == Problem.TYP_ULOHA)):
#			self.cislo_body = self.problem.cislo_reseni
#		super(Reseni, self).save(*args, **kwargs)

class Hodnoceni(SeminarModelBase):
	class Meta:
		db_table = 'seminar_hodnoceni'
		verbose_name = 'Hodnocení'
		verbose_name_plural = 'Hodnocení'

	# Interní ID
	id = models.AutoField(primary_key = True)


	body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='body',
							   blank=True, null=True)

	cislo_body = models.ForeignKey(Cislo, verbose_name='číslo pro body',
								   related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT)

	# V ročníku < 26 nastaveno na deadline vygenerovaný pro původní cislo_body
	deadline_body = models.ForeignKey(Deadline, verbose_name='deadline pro body',
								   related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT)

	reseni = models.ForeignKey(Reseni, verbose_name='řešení', on_delete=models.CASCADE)

	problem = models.ForeignKey(Problem, verbose_name='problém',
								related_name='hodnoceni', on_delete=models.PROTECT)

	feedback = models.TextField('zpětná vazba', blank=True, default='', help_text='Zpětná vazba řešiteli (plain text)')

	@property
	def body_celkem(self):
		# FIXME řeším jen prvního řešitele.
		return Hodnoceni.objects.filter(problem=self.problem, reseni__resitele=self.reseni.resitele.first(), body__isnull=False).aggregate(Sum("body"))["body__sum"]

	@body_celkem.setter
	def body_celkem(self, value):
		if value is None:
			self.body = None
		else:
			if self.body is None:
				self.body = 0
			if self.body_celkem is None:
				self.body += value
			else:
				self.body += value - self.body_celkem

	@property
	def body_neprepocitane(self):
		if self.body is None:
			return None
		return inverze_vzorecku_na_prepocet(self.body, self.reseni.resitele.count())

	@body_neprepocitane.setter
	def body_neprepocitane(self, value):
		if value is None:
			self.body = None
		else:
			self.body = vzorecek_na_prepocet(value, self.reseni.resitele.count())

	@property
	def body_neprepocitane_celkem(self):
		if self.body_celkem is None:
			return None
		return inverze_vzorecku_na_prepocet(self.body_celkem, self.reseni.resitele.count())

	@body_neprepocitane_celkem.setter
	def body_neprepocitane_celkem(self, value):
		if value is None:
			self.body = None
		else:
			self.body_celkem = vzorecek_na_prepocet(value, self.reseni.resitele.count())

	@property
	def body_max(self):
		if self.body_neprepocitane_max is None:
			return None
		return vzorecek_na_prepocet(self.body_neprepocitane_max, self.reseni.resitele.count())

	@property
	def body_neprepocitane_max(self):
		if not isinstance(self.problem.get_real_instance(), Uloha):
			return None
		return self.problem.uloha.max_body

	def __str__(self):
		return "{}, {}, {}".format(self.problem, self.reseni, self.body)

def generate_filename(self, filename):
	return os.path.join(
		settings.SEMINAR_RESENI_DIR,
		aux_generate_filename(self, filename)
	)


@reversion.register(ignore_duplicates=True)
class PrilohaReseni(SeminarModelBase):

	class Meta:
		db_table = 'seminar_priloha_reseni'
		verbose_name = 'Příloha řešení'
		verbose_name_plural = 'Přílohy řešení'
		ordering = ['reseni', 'vytvoreno']

	# Interní ID
	id = models.AutoField(primary_key = True)

	reseni = models.ForeignKey(Reseni, verbose_name='řešení', related_name='prilohy',
							   on_delete=models.CASCADE)

	vytvoreno = models.DateTimeField('vytvořeno', default=timezone.now, blank=True, editable=False)

	soubor = models.FileField('soubor', upload_to = generate_filename)

	poznamka = models.TextField('neveřejná poznámka', blank=True,
								help_text='Neveřejná poznámka k příloze řešení (plain text), např. o původu')

	res_poznamka = models.TextField('poznámka řešitele', blank=True,
									help_text='Poznámka k příloze řešení, např. co daný soubor obsahuje')

	def __str__(self):
		return str(self.soubor)

	def split(self):
		"Vrátí cestu rozsekanou po složkách. To se hodí v templatech"
		# Věřím, že tohle funguje, případně použít os.path nebo pathlib.
		return self.soubor.url.split('/')


# Vazebna tabulka. Mozna se generuje automaticky.
@reversion.register(ignore_duplicates=True)
class Reseni_Resitele(models.Model):

	class Meta:
		db_table = 'seminar_reseni_resitele'
		verbose_name = 'Řešení řešitelů'
		verbose_name_plural = 'Řešení řešitelů'
		ordering = ['reseni', 'resitele']

	# Interní ID
	id = models.AutoField(primary_key = True)

	resitele = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT)

	reseni = models.ForeignKey(Reseni, verbose_name='řešení', on_delete=models.CASCADE)

	# podil - jakou merou se ktery resitel podilel na danem reseni
	#	- pouziti v budoucnu, pokud by resitele nemeli dostat vsichni stejne bodu za spolecne reseni

	def __str__(self):
		return '{} od {}'.format(self.reseni, self.resitel)
	# NOTE: Poteciální DB HOG bez select_related