import statistics

from django.conf import settings
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect

from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login

from django.db.models import Min
from django.db.models import F
from django.db.models import Count

from .models import EggImage,EggTag,EggTagger

"""
##
# Index page
##
"""
def index(request):
    context = {}
    return render(request, "index.html", context)


"""
##
# Tag image page
##

Here we prefer images that have the least number of tags and pick at random
from those not already tagged by the current user
"""
def tag(request):
    # Get the db object for the logged-in tagger
    tagger = get_object_or_404(EggTagger, name=request.user.username)

    # Get all EggImage IDs associated with the tagger
    tagged_image_ids = EggTag.objects.filter(tagger=tagger).values_list('image_id', flat=True)

    # Get all images not tagged by user
    untagged_images = EggImage.objects.exclude(id__in=tagged_image_ids)
    
    # Find the minimum value in 'num_tags' (least tagged images)
    min_tags = untagged_images.aggregate(min_value=Min('num_tags'))['min_value']

    # Filter to only include images with that minimum value
    images_min_tagged = untagged_images.filter(num_tags=min_tags)

    # Select one at random
    random_image = images_min_tagged.order_by('?').first()

    # If none left to tag, redirect to success page
    if not random_image:
        return render(request, "success.html", {})

    # Get the dipslay url of the image
    display_url = random_image.image_path.replace(settings.IMAGE_DIR, "/images/")

    # Return a view of the selected image
    context = {
        "display_url":display_url,
        "tagger":tagger,
        "image_id":random_image.id,
        "tagger_id":tagger.id,
    }
    return render(request, "tag.html", context)


"""
##
# Add tag handler
##

Here we handle the form input for tagging an image
"""
def add_tag(request):
    # get the form values
    image_id = request.POST["image_id"]
    tagger_id = request.POST["tagger_id"]
    stage = request.POST["stage"]
    notag_reason = request.POST["notag_reason"]
    confidence = request.POST["confidence"]
    alt_stage = request.POST["alt_stage"]

    # handle blank inputs
    if not alt_stage:
        alt_stage = None

    # get objects
    image = get_object_or_404(EggImage, pk=image_id)
    tagger = get_object_or_404(EggTagger, pk=tagger_id)

    # create tag
    new_tag = EggTag(
        image=image,
        tagger=tagger,
        stage=stage,
        notag_reason=notag_reason,
        confidence=confidence,
        alt_stage=alt_stage
    )
    new_tag.save()

    # increment tag count
    image.num_tags = F("num_tags")+1
    image.save()

    # return to the tagging page
    return redirect("tag")


"""
##
# Stats page (general)
##
"""
def stats(request):
    #How many images?
    image_count = EggImage.objects.count()
    
    #How many tags?
    tag_count = EggTag.objects.count()
    
    #Proportion tagged?
    tagged_image_ids = EggTag.objects.values_list('image_id', flat=True)
    tagged_images = EggImage.objects.filter(id__in=tagged_image_ids).count()
    pc_tagged = round(tagged_images/image_count*100)

    #Proportion verified?
    verified_images = EggImage.objects.filter(num_tags__gt=1).count()
    pc_verified = round(verified_images/image_count*100)
    
    #Proportion unuseable?
    unusable_image_ids = EggTag.objects.filter(stage=0).values_list('image_id', flat=True)
    unusable_images = EggImage.objects.filter(id__in=unusable_image_ids).count()
    pc_unusable = round(unusable_images/image_count*100)
    
    #Average confidence?
    tagged_image_confidence = EggTag.objects.values_list('confidence', flat=True)
    mean_confidence = round(statistics.mean(tagged_image_confidence),1)
    
    #How many users?
    num_users = EggTagger.objects.count()
    
    #Top taggers?
    top_names = EggTag.objects.values('tagger__name').annotate(count=Count('tagger__name')).order_by('-count')[:10]
    # Render the results
    context = {
        'image_count':image_count,
        'tag_count':tag_count,
        'pc_tagged':pc_tagged,
        'pc_verified':pc_verified,
        'pc_unusable':pc_unusable,
        'mean_confidence':mean_confidence,
        'num_users':num_users,
        'top_names':top_names,
    }
    return render(request, "stats.html", context)


"""
##
# Stats page (user)
##
"""
def ustats(request):
    #How many tagged?
    #Average confidence?
    #My rank?
    context = {}
    return render(request, "ustats.html", context)


"""
##
# Login page
##

Use the builtin login page
"""
def login_view(request):
    if request.method == 'POST':
        form = AuthenticationForm(request, data=request.POST)
        if form.is_valid():
            user = form.get_user()
            login(request, user)
            return redirect("index")  
    else:
        form = AuthenticationForm()

    return render(request, 'login.html', {'form': form})


"""
##
# Register page
##

Use the builtin user creation page,
bu add a custom "experience" field and create an EggTagger object
"""
def register_view(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            # get username and custom "experience" field
            username = form.cleaned_data.get('username')
            exp = request.POST['experience']
            # create the EggTagger object
            new_tagger = EggTagger(
                name=username,
                experience=exp
            )
            # save the new tagger
            new_tagger.save()
            # save the new user
            form.save()
            # go to login page
            return redirect('login_view')  
    else:
        form = UserCreationForm()

    return render(request, 'register.html', {'form': form})
