import datetime
import logging
import unidecode

from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group
import django.contrib.auth

from .models import Osoba, Skola, Organizator, Resitel, Prijemce

logger = logging.getLogger(__name__)

User = django.contrib.auth.get_user_model()

zlinska = None  # tohle bude speciální škola, které později dodáme kontaktní osobu


# testuje unikátnost vygenerovaného jména
def __unikatni_jmeno(osoby, jmeno, prijmeni):
	for os in osoby:
		if os.jmeno == jmeno and os.prijmeni == prijmeni:
			return 0
	else:
		return 1


def gen_osoby(rnd, size):
	logger.info('Generuji osoby (size={})...'.format(size))

	jmena_m = ['Aleš', 'Tomáš', 'Martin', 'Jakub', 'Petr', 'Lukáš', 'Cyril', 'Pavel Karel']
	jmena_f = ['Eva', 'Karolína', 'Zuzana', 'Sylvie', 'Iva', 'Jana', 'Marie', 'Marta Iva', 'Shu Shan']
	prijmeni_m = ['Novotný', 'Svoboda', 'Pecha', 'Kořen', 'Holan', 'Uhlíř', 'Chytráček', 'Pokora', 'Koch', 'Szegedy', 'Rudý', "von Neumann", "d'Este"]
	prijmeni_f = ['Novotná', 'Svobodová', 'Machová', 'Zelená', 'Yu-Xin', 'Mlsná', 'Dubná', 'Mrkvová', 'Suchá', 'Lovelace', 'Holcová', 'Rui', "Nováčková Tydlitátová"]
	prezdivky = ['Kaki', 'Hurdur', 'Maracuja', 'Bobbo', "", "", "", "", "", "", "", 'Riki', 'Sapa', "", '', '---', 'Koko']
	domain = ['example.com', 'dolujeme.eu', 'mff.cuni.cz', 'strcprstskrzkrk.cz', 'british.co.uk', 'splachni.to', 'haha.org']
	seznam_ulic = ['Krátká', 'Vlhká', 'Jungmanova', '17. listopadu', '4. října', 'Roztocká', 'Forstova', 'Generála Františka Janouška', 'Náměstí Války', 'Svratecké náměstí', 'Zelená lhota', 'Z Plynu', 'K Jezeru', 'U Kocourkova', 'Uštěpačná', 'Ostrorepská', 'Zubří']
	seznam_mest = ['Praha', 'Brno', 'Ostrava', 'Horní Jelení', 'Dolní Zábrdovice', 'Prdelkov', 'Stará myslivna', 'Kocourkov', 'Šalingrad', 'Medvědí hora', 'Basilej', 'Unterschiedlich', 'Old York', 'Lancastershire', 'Vóloďháza']

	osoby = []
	# 30 je náhodná konstanta, size je použité na víc místech a
	# říká, jak velká asi chceme testovací data
	for i in range(30 * size):
		pohlavi_idx = rnd.randint(0, 2)  # 2 = nebinární
		osloveni = [Osoba.OSLOVENI_MUZSKE, Osoba.OSLOVENI_ZENSKE, Osoba.OSLOVENI_ZADNE][pohlavi_idx]
		jmeno = rnd.choice([jmena_m, jmena_f, jmena_m + jmena_f][pohlavi_idx])
		prijmeni = rnd.choice([prijmeni_m, prijmeni_f, prijmeni_m + prijmeni_f][pohlavi_idx])
		if pohlavi_idx == 2: logger.debug(f'Testdata: nebinární osoba: {jmeno} {prijmeni}.')
		pokusy = 0
		max_pokusy = 120*size
		while not __unikatni_jmeno and pokusy < max_pokusy:
			# pokud jméno a příjmení není unikátní, zkoušíme generovat nová
			# do daného limitu (abychom se nezacyklili do nekonečna při málo jménech a příjmeních
			# ze kterých se generuje)
			jmeno = rnd.choice([jmena_m, jmena_f, jmena_m + jmena_f][pohlavi_idx])
			prijmeni = rnd.choice([prijmeni_m, prijmeni_f, prijmeni_m + prijmeni_f][pohlavi_idx])
			pokusy += 1
		if pokusy >= max_pokusy:
			print("Chyba, na danou velikost testovacích dat příliš málo možných jmen a příjmení")
			exit()
		prezdivka = rnd.choice(prezdivky)
		email = "@".join([unidecode.unidecode(jmeno), rnd.choice(domain)])
		telefon = "".join([str(rnd.choice([k for k in range(10)])) for _ in range(9)])
		narozeni = datetime.date(
			rnd.randint(1980, datetime.datetime.now().year),
			rnd.randint(1, 12),
			rnd.randint(1, 28)
		)
		ulic = rnd.choice(seznam_ulic)
		cp = rnd.randint(1, 99)
		ulice = " ".join([ulic, str(cp)])
		mesto = rnd.choice(seznam_mest)
		psc = "".join([str(rnd.choice([k for k in range(10)])) for _ in range(5)])

		osoby.append(Osoba.objects.create(
			jmeno=jmeno, prijmeni=prijmeni,
			prezdivka=prezdivka, osloveni=osloveni,
			email=email, telefon=telefon,
			datum_narozeni=narozeni,
			ulice=ulice, mesto=mesto, psc=psc,
			datum_registrace=datetime.date(
				rnd.randint(2019, 2029), rnd.randint(1, 12), rnd.randint(1, 28)
			)
		))

	# TODO pridat foto male a velke. Jak?
	# Pavel tvrdí, že to necháme a přidáme až do adminu

	return osoby


def gen_skoly():  # TODO někdy to přepsat, aby jich bylo více
	logger.info('Generuji školy...')

	skoly = []
	prvnizs = Skola.objects.create(
		mesto='Praha', stat='CZ', psc='101 00',
		ulice='Krátká 5', nazev='První ZŠ', je_zs=True, je_ss=False,
	)
	skoly.append(prvnizs)
	skoly.append(Skola.objects.create(
		mesto='Praha', stat='CZ', psc='101 00',
		ulice='Krátká 5', nazev='První SŠ', je_zs=False, je_ss=True,
	))
	skoly.append(Skola.objects.create(
		mesto='Praha', stat='CZ', psc='102 00',
		ulice='Dlouhá 5', nazev='Druhá SŠ', je_zs=False, je_ss=True,
	))
	skoly.append(Skola.objects.create(
		mesto='Praha', stat='CZ', psc='103 00',
		ulice='Široká 3', nazev='Třetí SŠ a ZŠ', je_zs=True, je_ss=True,
	))
	skoly.append(Skola.objects.create(
		mesto='Ostrava', stat='CZ', psc='700 00',
		ulice='Hluboká 42', nazev='Hutní gympl', je_zs=False, je_ss=True,
	))
	skoly.append(Skola.objects.create(
		mesto='Humenné', stat='SK', psc='012 34',
		ulice='Pltká 1', nazev='Sredná škuola', je_zs=False, je_ss=True,
	))
	global zlinska
	zlinska = Skola.objects.create(
		mesto='Zlín', stat='CZ', psc='76001',
		ulice='náměstí T.G. Masaryka 2734-9',
		nazev='Gymnázium a Střední jazyková škola s právem SJZ',
		kratky_nazev="GaSJŠspSJZ", je_zs=True, je_ss=True,
	)
	skoly.append(zlinska)
	return skoly


def gen_resitele(rnd, osoby, skoly):
	logger.info('Generuji řešitele...')

	resitele = []
	x = 0
	resitel_perm = Permission.objects.filter(codename__exact='resitel').first()
	resitel_group = Group.objects.filter(name__exact='resitel').first()
	for os in osoby:
		rand = rnd.randint(0, 8)
		if not (rand % 8 == 0):
			if not os.user:
				if x:
					user = User.objects.create_user(
						username='r'+str(x), email=os.email, password='r',
					)
				else:
					user = User.objects.create_user(
						username='r', email=os.email, password='r',
					)
				x += 1
				os.user = user
				os.save()
				os.user.user_permissions.add(resitel_perm)
				os.user.groups.add(resitel_group)
			resitele.append(Resitel.objects.create(
				osoba=os, skola=rnd.choice(skoly),
				rok_maturity=os.datum_narozeni.year + rnd.randint(18, 21),
				zasilat=rnd.choice(Resitel.ZASILAT_CHOICES)[0],
			))
	return resitele


def gen_prijemci(rnd, osoby, kolik=10):
	logger.info('Generuji příjemce (kolik={})...'.format(kolik))
	prijemci = []
	for i in rnd.sample(osoby, kolik):
		prijemci.append(Prijemce.objects.create(osoba=i))

	global zlinska
	if zlinska is not None:
		zlinska.kontaktni_osoba=rnd.choice(osoby)
		zlinska.save()

	return prijemci


def gen_organizatori(rnd, osoby, last_rocnik):
	logger.info('Generuji organizátory...')
	organizatori = []


	seznam_konicku = ["vařím", "jezdím na kole", "řeším diferenciální rovnice", "koukám z okna", "tancuji", "programuji", "jezdím vlakem", "nedělám nic"]
	seznam_oboru = ["matematiku", "matematiku", "matematiku", "fyziku", "literaturu", "informatiku", "informatiku", "běhání dokolečka"]

	x = 0
	org_perm = Permission.objects.filter(codename__exact='org').first()
	org_group = Group.objects.filter(name__exact='org').first()
	for os in osoby:
		rand = rnd.randint(0, 8)
		if rand % 8 == 0:
			pusobnost = rnd.randint(1, last_rocnik)
			od = datetime.datetime(
				year=1993 + pusobnost,
				month=rnd.randint(1, 12),
				day=rnd.randint(1, 28),
				tzinfo=datetime.timezone.utc,
			)
			do = datetime.datetime(
				year=od.year + rnd.randint(1, 6),
				month=rnd.randint(1, 12),
				day=rnd.randint(1, 28),
				tzinfo=datetime.timezone.utc,
			)
			# aktualni organizatori jeste nemaji vyplnene organizuje_do

			# popis orga
			konicek1 = rnd.choice(seznam_konicku)
			konicek2 = rnd.choice(seznam_konicku)
			obor = rnd.choice(seznam_oboru)
			popis_orga = "Ve volném čase " + konicek1 + " a také " + konicek2 + ". Studuji " + obor + " a moc mě to baví."

			if do.year > datetime.datetime.now().year:
				do = None
			if not os.user:
				if x:
					user = User.objects.create_user(
						username='o'+str(x), email=os.email, password='o',
					)
				else:
					user = User.objects.create_user(
						username='o', email=os.email, password='o',
					)
				x += 1
				os.user = user
				os.save()
				os.user.user_permissions.add(org_perm)
				os.user.groups.add(org_group)
				os.user.is_staff = True
				os.user.save()
			organizatori.append(Organizator.objects.create(
				osoba=os,
				organizuje_od=od, organizuje_do=do,
				strucny_popis_organizatora=popis_orga,
			))
	return organizatori