from django.shortcuts import render
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.models import User as DjangoUser
from django.contrib.auth import authenticate, login
from django.core.mail import send_mail, mail_admins
from django.utils.datastructures import MultiValueDictKeyError
from datetime import date, datetime, timedelta
from urllib.parse import parse_qs
import requests
import json
import glob
import PIL.Image
import random
from collections import OrderedDict

from .models import User, ALKATOR_CHOICES_DICT, ALKATOR_CLASSES, Profile, Racer
from alkator.settings import COMGATE_MERCHANT, COMGATE_SECRET, COMGATE_TEST


@csrf_exempt
def register_user(request):
    if not request.POST['first_name']:
        return HttpResponse('{"reason":"Jméno je povinné!"}', status=400, content_type='application/json')
    if not request.POST['last_name']:
        return HttpResponse('{"reason":"Přijmení je povinné!"}', status=400, content_type='application/json')
    if not request.POST['email']:
        return HttpResponse('{"reason":"Email je povinný!"}', status=400, content_type='application/json')
    if not request.POST['address']:
        return HttpResponse('{"reason":"Adresa je povinná!"}', status=400, content_type='application/json')
    if not request.POST['password1'] or not request.POST['password2']:
        return HttpResponse('{"reason":"Heslo je povinné!"}', status=400, content_type='application/json')
    if request.POST['password1'] != request.POST['password2']:
        return HttpResponse('{"reason":"Hesla se neshodují!"}', status=400, content_type='application/json')
    if DjangoUser.objects.filter(email=request.POST['email']):
        return HttpResponse('{"reason":"Email je již registrován!"}', status=400, content_type='application/json')
    email = request.POST['email']

    user = DjangoUser.objects.create_user(
        email, email, request.POST['password1']
    )
    profile = Profile(user=user, first_name=request.POST['first_name'], last_name=request.POST['last_name'], address=request.POST['address'])
    profile.save()
    login(request, user)


@csrf_exempt
def login(request):
    try:
        user = authenticate(request, username=request.POST['email'], password=request.POST['password'])
    except MultiValueDictKeyError:
        return HttpResponse('{"reason":"Nezadané jméno nebo heslo!"}', status=400, content_type='application/json')
    if user is not None:
        login(request=request, user=user)
        return HttpResponse('{"success":"Úspěšně přihlášen uživatel '+ user.email + '"}', content_type='application/json')
    else:
        return HttpResponse('{"reason":"Nesprávné jméno nebo heslo!"}', status=400, content_type='application/json')


@csrf_exempt
def logout(request):
    logout(request)


@csrf_exempt
def register_racer(request):
    if not request.user.is_authenticated:
        return HttpResponse('{"reason":"Je potřeba se přihlásit!"}', status=400, content_type='application/json')
    ALKATOR_CLASS = 3

    if date.today() >= date(2024, 10, 5):
        return HttpResponse('{"reason":"Too late!"}', status=400, content_type='application/json')
    if not request.POST.get('agreement'):
        return HttpResponse('{"reason":"Je potřeba souhlasit se zpracováním údajů!"}', status=400, content_type='application/json')
    if not request.POST['first_name']:
        return HttpResponse('{"reason":"Jméno je povinné!"}', status=400, content_type='application/json')
    if not request.POST['last_name']:
        return HttpResponse('{"reason":"Přijmení je povinné!"}', status=400, content_type='application/json')
    if Racer.objects.filter(alkator_class=ALKATOR_CLASS, paid=True).count() >= 100:
        return HttpResponse('{"reason":"Kapacita závodu byla naplněna!"}', status=400, content_type='application/json')
    try:
        dat = datetime.strptime(request.POST['date_of_birth'], "%Y-%m-%d").date()
        if dat > date(2006, 10, 5):
            return HttpResponse('{"reason":"Je potřeba mít 18 let v den závodu!"}', status=400, content_type='application/json')
        elif dat < date(1924, 10, 5):
            return HttpResponse('{"reason":"Opravdu vám je 100 let?"}', status=400, content_type='application/json')
    except:
        return HttpResponse('{"reason":"Špatný formát datu narození!"}', status=400, content_type='application/json')

    invoice_date = datetime.today()
    invoice_id = invoice_date.year * 1000000 + invoice_date.month * 10000 + invoice_date.day * 100

    try:
        latest_racer = Racer.objects.latest("invoice_id")
        if latest_racer.invoice_id is None or latest_racer.invoice_id < invoice_id:
            invoice_id = invoice_id + 1
        else:
            invoice_id = latest_racer.invoice_id + 1
    except User.DoesNotExist:
        invoice_id = invoice_id + 1

    if date.today() >= date(2024, 9, 21):
        price = 79000
    else:
        price = 69000

    profile = request.user.profile
    user = request.user

    racer = Racer(
        profile = profile,
        first_name = request.POST['first_name'],
        last_name = request.POST['last_name'],
        email = request.POST['email'],
        team = request.POST['team'],
        phone = request.POST['phone'],
        date_of_birth = dat,
        alkator_class = ALKATOR_CLASS,
        price = price,
        invoice_id = invoice_id,
    )
    racer.save()

    payment_data = {
        'merchant': COMGATE_MERCHANT,
        'test': 'true' if COMGATE_TEST else 'false',
        'price': price,
        'curr': 'CZK',
        'method': 'ALL',
        'label': 'Startovné na závod Alkátor Race Studené 2024',
        'email': user.email,
        'fullName': f"{profile.first_name} {profile.last_name}",
        'refId': f'{racer.invoice_id}',
        'secret': COMGATE_SECRET,
        'prepareOnly': 'true',
    }
    result = requests.post('https://payments.comgate.cz/v1.0/create', data=payment_data)

    result = parse_qs(result.text)

    if result['code'][0] != '0':
        racer.delete()
        return HttpResponse('{"reason":"Chyba na straně platební brány: ' + result['message'][0] + ', zkuste prosím registraci později."}', status=400, content_type='application/json')

    racer.trans_id = result['transId'][0]
    racer.save()

    return HttpResponse('{"success":"", "redirect":"' + result['redirect'][0] + '"}', content_type='application/json')


def login_status(request):
    if not request.user.is_authenticated:
        return HttpResponse('{}', content_type='application/json')

    user = request.user
    racers = user.profile.racers
    return HttpResponse(json.dumps({
        "email": user.email,
        "first_name": user.profile.first_name,
        "last_name": user.profile.last_name,
        "address": user.profile.address,
        "racers": [{
            "first_name": racer.first_name,
            "last_name": racer.last_name,
            "email": racer.email,
            "team": racer.team,
            "date_of_birth": racer.date_of_birth,
            "paid": racer.paid,
        } for racer in racers]
    }), content_type='application/json')


#@csrf_exempt
#def register(request):
#    ALKATOR_CLASS = 2
#
#    if date.today() >= date(2024, 10, 5):
#        return HttpResponse('{"reason":"Too late!"}', status=400, content_type='application/json')
#    if not request.POST.get('agreement'):
#        return HttpResponse('{"reason":"Je potřeba souhlasit se zpracováním údajů!"}', status=400, content_type='application/json')
#    if not request.POST['first_name']:
#        return HttpResponse('{"reason":"Jméno je povinné!"}', status=400, content_type='application/json')
#    if not request.POST['last_name']:
#        return HttpResponse('{"reason":"Přijmení je povinné!"}', status=400, content_type='application/json')
#    if not request.POST['email']:
#        return HttpResponse('{"reason":"Email je povinný!"}', status=400, content_type='application/json')
#    if not request.POST['address']:
#        return HttpResponse('{"reason":"Adresa je povinná!"}', status=400, content_type='application/json')
#    if not request.POST['phone']:
#        return HttpResponse('{"reason":"Telefoní číslo je povinný!"}', status=400, content_type='application/json')
#    if User.objects.filter(email=request.POST['email'], alkator_class=ALKATOR_CLASS):
#        return HttpResponse('{"reason":"Email je již registrován!"}', status=400, content_type='application/json')
#    if User.objects.filter(alkator_class=ALKATOR_CLASS, paid=True).count() >= 50:
#        return HttpResponse('{"reason":"Kapacita závodu byla naplněna!"}', status=400, content_type='application/json')
#    try:
#        dat = datetime.strptime(request.POST['date_of_birth'], "%Y-%m-%d").date()
#        if dat > date(2006, 10, 5):
#            return HttpResponse('{"reason":"Je potřeba mít 18 let v den závodu!"}', status=400, content_type='application/json')
#        elif dat < date(1924, 10, 5):
#            return HttpResponse('{"reason":"Opravdu vám je 100 let?"}', status=400, content_type='application/json')
#    except:
#        return HttpResponse('{"reason":"Špatný formát datu narození!"}', status=400, content_type='application/json')
#
#    invoice_date = datetime.today()
#    invoice_id = invoice_date.year * 1000000 + invoice_date.month * 10000 + invoice_date.day * 100
#
#    try:
#        latest_user = User.objects.latest("invoice_id")
#        if latest_user.invoice_id is None or latest_user.invoice_id < invoice_id:
#            invoice_id = invoice_id + 1
#        else:
#            invoice_id = latest_user.invoice_id + 1
#    except User.DoesNotExist:
#        invoice_id = invoice_id + 1
#
#    if date.today() >= date(2024, 9, 21):
#        price = 79000
#    else:
#        price = 69000
#
#    user = User(
#        first_name=request.POST['first_name'],
#        last_name=request.POST['last_name'],
#        email=request.POST['email'],
#        date_of_birth=dat,
#        address=request.POST['address'],
#        phone=request.POST['phone'],
#        alkator_class=ALKATOR_CLASS,
#        invoice_id=invoice_id,
#        price=price//100
#    )
#    user.save()
#
#    payment_data = {
#        'merchant': COMGATE_MERCHANT,
#        'test': 'true' if COMGATE_TEST else 'false',
#        'price': price,
#        'curr': 'CZK',
#        'method': 'ALL',
#        'label': 'Startovné na závod Alkátor Race Studené 2024',
#        'email': user.email,
#        'fullName': f"{user.first_name} {user.last_name}",
#        'refId': f'{user.invoice_id}',
#        'secret': COMGATE_SECRET,
#        'prepareOnly': 'true',
#    }
#    result = requests.post('https://payments.comgate.cz/v1.0/create', data=payment_data)
#
#    result = parse_qs(result.text)
#
#    if result['code'][0] != '0':
#        user.delete()
#        return HttpResponse('{"reason":"Chyba na straně platební brány: ' + result['message'][0] + ', zkuste prosím registraci později."}', status=400, content_type='application/json')
#
#    user.trans_id = result['transId'][0]
#    user.save()
#
#    return HttpResponse('{"success":"", "redirect":"' + result['redirect'][0] + '"}', content_type='application/json')


@csrf_exempt
def payment_result(request):
    result = parse_qs(request.body.decode('utf8'))
    ref_id = int(result['refId'][0])
    paid = result['status'][0]
    secret_match = result['secret'][0] == COMGATE_SECRET
    test = result['test'][0] != 'false'
    if not secret_match or test != COMGATE_TEST:
        return HttpResponse(status=400)
    try:
        racer = Racer.objects.get(invoice_id=ref_id)
    except Racer.DoesNotExist:
        mail_admins('Chyba s platbou!', f'invoice_id={ref_id}&paid={paid}')
        return HttpResponse(status=404)
    if paid == 'PAID':
        racer.paid = True
        racer.save()
        send_mail(
            f"úspěšná registrace do závodu Alkátor race Dolní Čermná ({racer.first_name} {racer.last_name})",
            f"""Zdravím tě Alkátore,
toto je potvrzovací email o účasti v nezapomenutelném závodě Alkátor-race.
Prosíme kontrolujete si své hromadné schránky a spamy.

Závod se koná 5.10.2024 v Dolní Čermné.
Zajištěno je stanování, občerstvení a také večerní after párty.

Připrav na zkoušku své tělo, játra a tvé mozkové buňky.
Budou tě čekat nevídané překážky.

O podrobnostech tě budeme informovat emailem.
Nezapomeň nás sledovat na Facebooku, Instagramu, YouTube a TikToku.

Na tento email není třeba odpovídat, protože je generován automaticky s přijatou platbou. V případě potřeby pište na info@alkator.cz .

ALKÁTOR TEAM
email: info@alkator.cz
tel: + 420 728 018 088
web: https://alkator.cz""",
            "info@alkator.cz",
            [racer.profile.user.email, racer.email] if racer.email else [racer.profile.user.email],
        )
    elif paid == 'CANCELLED' and not user.paid:
        racer.delete()
    return HttpResponse(status=200)


def payment_state(request):
    invoice_id = request.GET['refId']
    try:
        if Racer.objects.get(invoice_id=invoice_id).paid:
            return HttpResponse('{"status":"success", "reason":"Úspěšná platba"}', content_type='application/json')
        else:
            return HttpResponse('{"status":"failed", "reason":"Zatím nemáme informace o provedené platbě. Zkuste reload nebo zkontrolujte email."}', content_type='application/json')
    except Racer.DoesNotExist:
        return HttpResponse('{"status":"failed", "reason":"Závodník neexistuje, registraci závodníka prosím opakujte."}', content_type='application/json')


def results(request):
    results = []
    n = 1
    for user in User.objects.filter(alkator_class=2).order_by('duration'):
        if user.duration:
            if user.alkator_category == 1:
                order = f'{n}.'
                n += 1
            else:
                order = 'x.'
            results.append({
                'order': order,
                'duration': str(user.duration),
                'alkator_category': ALKATOR_CHOICES_DICT[user.alkator_category],
                'starting_number': user.starting_number,
            })
    for user in User.objects.filter(alkator_class=2).order_by('duration'):
        if not user.duration and user.starting_number:
            results.append({
                'order': 'DNF',
                'duration': 'Nedokončil',
                'starting_number': user.starting_number,
                'alkator_category': ''
            })

    return HttpResponse(json.dumps(results), content_type='application/json')


def photos(request):
    rtn = []
    for (i, name) in ALKATOR_CLASSES[:2]:
        photos = {}
        rtn.append(photos)
        photos['name'] = name
        photos['index'] = i
        photos['photos'] = []
        files = glob.glob(f"photos/{i}/*.jpg")
        random.shuffle(files)
        for file in files:
            img = PIL.Image.open(file)
            photos['photos'].append({
                'original': '/' + file.replace(".jpg", ".webp"),
                'thumbnail': '/' + file.replace(f'photos/{i}/', f'photos/{i}/thumbnail/').replace(".jpg", ".webp"),
                'original_width': img.width,
                'original_height': img.height,
            })

    return HttpResponse(json.dumps(rtn), content_type='application/json')


@csrf_exempt
def upload_files(request):
    for file in request.FILES.getlist('files'):
        rand = random.randint(0, 99999)
        random_name = f'photos/uploads/{rand}_{file.name}'
        with open(random_name, "wb+") as destination:
            for chunk in file.chunks():
                destination.write(chunk)
    return HttpResponse('{"success":"Úspěšně nahráno! Počkejte až dojde ke schválení nahraných souborů."}', content_type='application/json')


@staff_member_required
def invoice(request):
    user = User.objects.get(invoice_id=request.GET['invoice_id'])
    return TemplateResponse(
        None,
        'invoice.html',
        {
            'user': user,
            'paid_date': user.register_date + timedelta(days=1),
        }
    )
