from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, JsonResponse
from .models import Poll, Participant, Type, Possibility, Question, QuestionPossibility, Answer, PollParticipant
from django.views.decorators.csrf import csrf_exempt
from django.urls import reverse
import uuid
from .forms import ParticipantForm, UploadFileForm 
from .utils import  handle_uploaded_file, extract_number, new_possibilities_ids, getQuestionsByOrder, getAnsweredQuestions, questionOrder, getFirstQuestionNotAnsweredIndex, send_email
from django.template.defaulttags import register


# Create your views here.
@login_required
def home(request):
    user_polls = Poll.objects.filter(user=request.user).order_by('-created_at')[:8]
    
    participants_polls = Participant.objects.filter(user=request.user)
    return render(request, 'home/index.html', {'user_polls' : user_polls, 'participants_polls': participants_polls, 'all_polls': Poll.objects.filter(user=request.user)})


# @login_required
# def create_polls(request):
#     return render(request, 'polls/edit-add.html')

# @login_required
# def store_polls(request):
#     if request.method == 'POST':
#         title = request.POST['title']
#         description = request.POST['description']
        
#         poll = Poll(title=title, description=description, user=request.user)
#         poll.save()
#         return redirect('home')
#     else:
#         return render(request, 'polls/edit-add.html')
   

@csrf_exempt
def store_polls(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        description = request.POST.get('description')
        
        if request.POST.get('id'):
            poll = get_object_or_404(Poll, id=int(request.POST.get('id')))
            poll.title = title.capitalize()
            poll.description = description.capitalize()
            poll.save()
            return JsonResponse({'message':'Poll updated successfully'}, status=200)
        else:
            poll = Poll(title=title, description=description, user=request.user)
            poll.save()
            return JsonResponse({'message':'Poll saved successfully'}, status=200)
    else:
        return JsonResponse({'error': 'Invalid request'}, status=400)

@login_required
def polls(request):
    polls = Poll.objects.filter(user=request.user)
    return render(request, 'polls/index.html', {'polls': polls})

@csrf_exempt
def edit_polls(request, id):
    poll = get_object_or_404(Poll, id=id)
    if request.method == 'GET':
        data = {
            'id': poll.id,
            'title': poll.title,
            'description': poll.description
        }
        return JsonResponse(data)
    else:
        return JsonResponse({'error': 'Invalid request'}, status=400)
    
@csrf_exempt
def delete_polls(request, id):
    poll = get_object_or_404(Poll, id=id)
    poll.delete()    
    return JsonResponse({'message' : 'question deleted successfully'}, status=200)
    

# Questions views
# @login_required
# def manage_questions(request, id):
#     if id not in [poll.id for poll in Poll.objects.filter(user=request.user)]:
#         return redirect('home')
#     if request.method == 'POST':
#         print(request.POST.get('label'), request.POST.get('type'),)
#         form = QuestionForm(request.POST)
#         # if form.is_valid():
#         #     label = form.cleaned_data['label']
#         #     type_id = form.cleaned_data['type']
#         #     possibilities = form.cleaned_data['possibilities']
#         #     poll = Poll.objects.get(id=id)
#         #     question = Question(label=label, type_id=type_id)
#         #     question.save()
#         #     question.possibilities.set(possibilities)
#         #     poll.questions.add(question)
            
#             # return redirect('polls.questions.manage', {'id':id, 'message': 'Question enregistrée avec succès'})
#     else:
#         print('no valid')
#         form = QuestionForm(types=Type.objects.all(), possibilities=Possibility.objects.all())
# 
#   return render(request, 'questions/manage_questions.html', {'current_poll': Poll.objects.filter(user=request.user, id=id).first(), 'form':form})


@login_required
def manage_questions(request, id):
    if id not in [poll.id for poll in Poll.objects.filter(user=request.user)]:
        return redirect('home')
    if request.method == 'POST':
        label = request.POST.get('label')
        type_id = request.POST.get('type')
        possibilities = request.POST.get('possibilities')
        poll = Poll.objects.get(id=id)
        if label and type_id:
            question = Question(label=label, type_id=type_id)
            question.save()
            if possibilities:
                possibilities = [int(possibility) for possibility in possibilities.split(',')]
                question.possibilities.set(possibilities)
            else: # if no possibilities are selected, create a QuestionPossibility object with question and null possibility for free type question
                QuestionPossibility.objects.create(question=question)
            poll.questions.add(question)          
            
            return redirect('polls.questions.manage', id=id)
        
    return render(request, 'questions/manage_questions.html', {'current_poll': Poll.objects.filter(user=request.user, id=id).first(), 'types': Type.objects.all(), 'possibilities': Possibility.objects.all()})

# Questions json response
@csrf_exempt
def save_questions(request, id):
    if request.method == 'POST':
        print(request.POST)
        label = request.POST.get('label')
        type_id = request.POST.get('type')
        possibilities_datas = request.POST.getlist('possibilities[]')
        if request.POST.get('qid'):
            question = get_object_or_404(Question, id=int(request.POST.get('qid')))
            question.label = label.capitalize()
            question.type.id = type_id
            question.possibilities.set(new_possibilities_ids(possibilities_datas))
            question.save()
        else:
            poll = get_object_or_404(Poll, id=id)
            if label and type_id:
                question = Question(label=label, type_id=type_id)
                question.save()
                if possibilities_datas:
                    question.possibilities.set(new_possibilities_ids(possibilities_datas))
                else: # if no possibilities are selected, create a QuestionPossibility object with question and null possibility for free type question
                    QuestionPossibility.objects.create(question=question)
            poll.questions.add(question)
        return JsonResponse({'message':'Data saved successfully'}, status=200)
    else:
        return JsonResponse({'error': 'Invalid request'}, status=400)

@csrf_exempt
def edit_question(request, id, qid):
    question = get_object_or_404(Question, id=qid)
    if request.method == 'GET':
        data = {
            'qid': qid,
            'label': question.label,
            'type': question.type.id,
            'possibilities': [p.id for p in question.possibilities.all()]
        }
        return JsonResponse(data) 
    return JsonResponse({'error': 'Invalid request'}, status=400)

def delete_question(request, id, qid):
    question = get_object_or_404(Question, id=qid)
    question.delete()    
    return JsonResponse({'message' : 'question deleted successfully'}, status=200)

# Possibilities json response
@csrf_exempt
def possibilities(request):
    if request.method == 'POST':
        lab = request.POST.get('lab')
        possibility = Possibility(label=lab)        
        possibility.save()
        return JsonResponse({'message':'Data saved successfully', 'label': possibility.label, 'id': possibility.id}, status=200)
    else:
        return JsonResponse({'error': 'Invalid request'}, status=400)
    
    
# participants views
def participants(request):
    participants = Participant.objects.filter(user=request.user)
    form = ParticipantForm()
    file_form = UploadFileForm()
    if request.method == 'POST':
        if 'manual' in request.POST.keys():
            form = ParticipantForm(request.POST) 
            if form.is_valid():
                print('here')
                participant = form.save(commit=False)
                participant.user = request.user
                participant.token = uuid.uuid4()
                participant.save()
                return redirect('participants.index')
        if 'import' in request.POST.keys(): 
            file_form = UploadFileForm(request.POST, request.FILES)
            if file_form.is_valid():
                handle_uploaded_file(request.FILES['fichier'], request.user)
                return redirect('participants.index')     
    return render(request, 'participants/index.html', {'form': form, 'participants': participants, 'file_form' : file_form})

def participant_delete(request, id):
    participant = get_object_or_404(Participant, id=id)
    participant.delete()    
    return redirect('participants.index')
    

# Share poll views
@login_required
@csrf_exempt
def share_poll(request, id):
    participants = Participant.objects.filter(user=request.user)
    poll = get_object_or_404(Poll, id=id)
    if len(poll.questions.all()) == 0:
        return render(request, 'participants/share.html', {'poll': poll, 'informations': []})           
    
    if request.method == 'POST':
        print(request.POST)
        receivers = request.POST.get('receivers').split(',')
        print(receivers)
        
        template = 'participants/email.html'
        subject = f"Participation au sondage {poll.title}"
        context = {
            'title': poll.title,
        }
        
        for receiver in receivers:
            participant = get_object_or_404(Participant, email=receiver)
            context['name'] = f"{participant.last_name} {participant.first_name}"
            context['link'] = request.build_absolute_uri(reverse('pollls.respond', args=[poll.token, participant.token]))
            has_send = send_email(subject=subject, receivers=[receiver], template=template, context=context)
            if (not has_send):
                return HttpResponse('<div class="alert alert-danger text-center">Erreur lors de l\'envoi des emails </div>')
            poll_participant = get_object_or_404(PollParticipant, poll=poll, participant=participant)
            poll_participant.is_emailed = True
        return HttpResponse('<div class="alert alert-success text-center">Emails envoyés avec succès </div>')
    
    informations = []
    for participant in participants:
        # cree un participant pour chaque sondage, si le participant existe deja, il ne sera pas cree
        poll_participant, created = PollParticipant.objects.get_or_create(poll=Poll.objects.get(id=id), participant=participant)
        #print(poll_participant, created)
        informations.append({
            'full_name': f"{participant.last_name} {participant.first_name}",
            'link': request.build_absolute_uri(reverse('pollls.respond', args=[Poll.objects.get(id=id).token, participant.token])),
            'email': participant.email,
            'submitted': poll_participant.has_submitted,
            'emailed': poll_participant.is_emailed
        })

    return render(request, 'participants/share.html', {'poll': poll, 'informations': informations})

@csrf_exempt
def send_vial_mail(request, id):
    poll = get_object_or_404(Poll, id=id)
    if request.method == 'POST':
        print(request.POST)
        # receivers = request.POST.get('receivers').split(',')
        # print(receivers)
        
        # template = 'participants/email.html'
        # subject = f"Participation au sondage {poll.title}"
        # context = {
        #     'title': poll.title,
        # }
        
        # for receiver in receivers:
        #     participant = get_object_or_404(Participant, email=receiver)
        #     context['name'] = f"{participant.last_name} {participant.first_name}"
        #     context['link'] = request.build_absolute_uri(reverse('pollls.respond', args=[poll.token, participant.token]))
        #     send_email(subject=subject, template=template, context=context, receivers=[receiver])
            # poll_participant = get_object_or_404(PollParticipant, poll=poll, participant=participant)
            # poll_participant.is_emailed = True
        return JsonResponse({'message':'Email sent successfully'}, status=200)
    return JsonResponse({'error': 'Invalid request'}, status=400)


def respond_poll(request, token, key):
    participant = Participant.objects.filter(token=key).first()
    poll = Poll.objects.filter(token=token).first()
    if not (participant and poll) :
        return HttpResponse('<h2 style="text-align:center;">⚠ Oups😅 Le lien est invalide ⚠</h2>')
        
    poll_participant = get_object_or_404(PollParticipant, poll=poll, participant=participant)
    if len(poll.questions.all()) == 0:
        return HttpResponse(f"<h2 style='text-align:center;'>⚠ Oups😅Le sondage \"{poll.title}\" ne contient aucune question pour le moment ⚠</h2>")
    
    # recupérer les questions et les réponses deja enregistrées avant soumission
    questions = poll.questions.all()
    answers = Answer.objects.filter(poll_participant=poll_participant)
    
    answered_questions = {}
    for answer in answers:
        if not answer.question_possibility.possibility:
            answered_questions[answer.question_possibility.question.id] = answer.content
        else:
            if answer.question_possibility.question.id not in answered_questions.keys():
                answered_questions[answer.question_possibility.question.id] = [answer.question_possibility.possibility.id]
                print(answer.question_possibility)
            else:
                answered_questions[answer.question_possibility.question.id].append(answer.question_possibility.possibility.id)
                print(answer.question_possibility)         
    print('answered_questions :', answered_questions)
      
     # Trouver la première question non répondue
    first_unanswered_index = 1
    for index, question in enumerate(questions, start=1):
        if question.id not in answered_questions:
            first_unanswered_index = index
            break
    print('first_answered_index : ',first_unanswered_index)
    
    if request.method == 'POST':
        print(poll_participant)
        poll_participant.has_submitted = True
        poll_participant.save()
        return HttpResponse('<h2 style="text-align:center;">🙏🏽Merci pour votre participation🙏🏽</h2>')
    if poll_participant.has_submitted:
        return HttpResponse(f'<h2 style="text-align:center;">⚠ Oups😅Vous avez déjà soumis vos réponses au sondage "{poll.title}" ⚠</h2>')
    return render(request, 'responses/questionnaire.html', {'poll': get_object_or_404(Poll, token=token), 'participant':  get_object_or_404(Participant, token=key), 'answered_questions': answered_questions, 'first_unanswered_index': first_unanswered_index})

@csrf_exempt
def save_one(request, token, key):
    if request.method == 'POST':
        print('in save_one method', request.POST.keys())
        poll = get_object_or_404(Poll, token=token)
        participant = get_object_or_404(Participant, token=key)
        poll_participant = get_object_or_404(PollParticipant, poll=poll, participant=participant)
        for key in request.POST:
            if key.startswith('question'):
                question_id = extract_number(key)
                question = get_object_or_404(Question, id=question_id)
                values = request.POST.getlist(key)
                # values =  request.POST.getlist(key) if (question.type.label == 'Multiple') else request.POST.get(key)
                print(values) 
                
                if "libre" not in key:
                    Answer.objects.filter(poll_participant=poll_participant, question_possibility__question=question).delete()
                    for value in values:
                        question_possibility = get_object_or_404(QuestionPossibility, question=question, possibility=int(value))
                        Answer.objects.create(question_possibility=question_possibility, poll_participant=poll_participant)
                else:
                    question_possibility = get_object_or_404(QuestionPossibility, question=question)
                    print('question-possibility : ', question_possibility)
                    answer, created = Answer.objects.get_or_create(poll_participant=poll_participant, question_possibility=question_possibility, defaults={'content': values[0]})
                    print(answer, created)
                    if not created:
                       answer.content = values[0]
                       answer.save()
                # if "libre" not in key:
                #     for value in values:
                #         question_possibility = get_object_or_404(QuestionPossibility, question=question, possibility=int(value))
                #         print(question_possibility)
                #         Answer.objects.create(question_possibility=question_possibility, participant=participant)
                # else:
                #     question_possibility = get_object_or_404(QuestionPossibility, question=question)
                #     print(question_possibility)
                #     Answer.objects.create(participant=participant, question_possibility=question_possibility, content=values[0])
        return JsonResponse({'status':'Saved successfully'}, status=200)
    else:
        return JsonResponse({'status':'Invalid request'}, status=400)

def respond_polll(request, token, key):
    participant = get_object_or_404(Participant, token=key)
    poll = get_object_or_404(Poll, token=token)
    poll_participant = get_object_or_404(PollParticipant, poll=poll, participant=participant)
    
    if poll_participant.has_submitted:
        return HttpResponse(f'<h2 style="text-align:center;">⚠ Oups😅Vous avez déjà soumis vos réponses au sondage "{poll.title}" ⚠</h2>')
    
    
    if 'final-submit' in request.POST.keys():
        poll_participant.has_submitted = True
        # poll_participant.participant.token = uuid.uuid4()
        poll_participant.save()
        return HttpResponse('<h2 style="text-align:center;">🙏🏽Merci pour votre participation🙏🏽</h2>')

    answers = Answer.objects.filter(poll_participant=poll_participant)
    order = getFirstQuestionNotAnsweredIndex(poll.questions.all(), getAnsweredQuestions(answers))
    answered_questions = getAnsweredQuestions(answers)
    return render(request, 'responses/quest.html', {
        'question': getQuestionsByOrder(poll.questions.all(), order),
        'poll': poll,
        'participant': participant,
        'order': order,
        'nbTotal': poll.questions.count(), 
        'answered_questions': answered_questions
    })

@csrf_exempt
def save_question_htmx(request, qid, token, key):
    poll = get_object_or_404(Poll, token=token)
    participant=get_object_or_404(Participant, token=key)
    poll_participant = get_object_or_404(PollParticipant, poll=poll, participant=participant) 
    question = get_object_or_404(Question, id=qid)
    question_answers = Answer.objects.filter(poll_participant=poll_participant, question_possibility__question=question) # participants answer for the current question
    all_answers = Answer.objects.filter(poll_participant=poll_participant) # all participants answers

    if request.method == 'POST':
        if 'final-submit' in request.POST.keys():
            poll_participant.has_submitted = True
            poll_participant.save()
            return HttpResponse('<h2 style="text-align:center;">🙏🏽Merci pour votre participation🙏🏽</h2>')
        
        # save the current question and move to the next or previous question
        values = request.POST.getlist('question')
        if question.type.label == 'Unique':
            if(len(values) > 0):
                answer = question_answers.first()
                if not answer:
                    question_possibility = get_object_or_404(QuestionPossibility, question=question, possibility=int(values[0]))
                    Answer.objects.create(question_possibility=question_possibility, poll_participant=poll_participant)
                else:
                    answer.question_possibility = get_object_or_404(QuestionPossibility, question=question, possibility=Possibility.objects.get(id=int(values[0])))
                    answer.save()
        elif question.type.label == 'Libre':
            question_possibility = get_object_or_404(QuestionPossibility, question=question) #Ici le possibility du qustion_possibility est null
            print('Toiiiiiiiiiiiiiiiiiiii : ', question_possibility)
            if (len(values[0]) > 0):
                answer, created = Answer.objects.get_or_create(question_possibility=question_possibility, poll_participant=poll_participant, defaults={'content': values[0]})
                print(answer, created)
                if not created:
                    answer.content = values[0].strip()
                    answer.save()
        else:
            Answer.objects.filter(poll_participant=poll_participant, question_possibility__question=question).delete()
            print('values : ', values)
            for value in values:
                question_possibility = get_object_or_404(QuestionPossibility, question=question, possibility=int(value))
                Answer.objects.create(question_possibility=question_possibility, poll_participant=poll_participant)
        
        order =  int(request.POST.get('order-next')) if ('next-button' in request.POST) else int(request.POST.get('order-prev')) 

        answered_questions = getAnsweredQuestions(all_answers)
        # print(answered_questions, len(answered_questions), poll.questions.count(), order, getQuestionsByOrder(poll.questions.all(), order), poll.questions.count() == len(answered_questions))
        if not getQuestionsByOrder(poll.questions.all(), order):
            order = getFirstQuestionNotAnsweredIndex(poll.questions.all(), answered_questions)
        
        if poll.questions.count() == len(answered_questions) and order == len(answered_questions):
            return render(request, 'responses/summary.html', {'poll': poll, 'participant': participant, 'answered_questions': answered_questions, 'order': order + 1})
        return render(request, 'responses/form.html', {'poll': poll, 'participant': participant, 'question': getQuestionsByOrder(poll.questions.all(), order), 'order': order, 'nbTotal': poll.questions.count(), 'answered_questions': answered_questions})

    order = questionOrder(poll.questions.all(), question)    
    return render(request, 'responses/form.html', {'poll': poll, 'participant': participant, 'question': getQuestionsByOrder(poll.questions.all(), order), 'order': order, 'nbTotal': poll.questions.count(), 'answered_questions': getAnsweredQuestions(all_answers)})

# statistics views
def stats(request):
    polls = Poll.objects.filter(user=request.user)
    selected_poll = Poll.objects.latest('created_at')   
    return render(request, 'statistics/index.html', {
        'polls': polls,
        'selected_poll': selected_poll,
    })
    
def stats_data(request, id):
    selected_poll = get_object_or_404(Poll, id=id)
    questions = selected_poll.questions.all()
    question_stats = []
    
    for question in questions:
        stats = {'question': question.label, 'type': question.type.label, 'responses': {}}
        
        if question.type.label == 'Libre':
            answers = Answer.objects.filter(question_possibility__question=question, poll_participant__has_submitted=True)
            stats['responses'] = [answer.content for answer in answers]
        else:
            possibilities = QuestionPossibility.objects.filter(question=question)
            for possibility in possibilities:
                label = possibility.possibility.label if possibility.possibility else 'None'
                stats['responses'][label] = Answer.objects.filter(question_possibility=possibility, poll_participant__has_submitted=True).count()
        question_stats.append(stats) 
        
    # print(len(question_stats))
        
    return JsonResponse({
        'poll': {'title': selected_poll.title, 'description': selected_poll.description},
        'question_stats': question_stats,
    })       
    # return render(request, 'statistics/index.html', {
    #     'polls': polls,
    #     'selected_poll': selected_poll,
    #     'question_stats': question_stats,
    # })
    
# custom template tags
@register.filter
def get_item(dictionary, key):
    return dictionary.get(key)

@register.filter
def percentage(a, b):
    return a / b * 100

@register.filter
def possibility_str(answers, qId):
    if isinstance(answers[qId], list):
        if len(answers[qId]) == 1:
            return get_object_or_404(Possibility, id=answers[qId][0]).label
        else:
            return ', '.join([get_object_or_404(Possibility, id=id).label for id in answers[qId]])
    else:
        return answers[qId]
    
    
    