import csv
import json
import requests
from difflib import SequenceMatcher
from django.utils import timezone
from django.conf import settings

from .models import Review, CustomReply


# constants
nlu_server_url = settings.NLU_SERVER_URI
replies = CustomReply.objects.all()


def model_inference(text):
    url = nlu_server_url + '/model/parse'
    payload = {'text': text}
    headers = {'content-type': 'application/json'}
    response = requests.post(url, data=json.dumps(payload), headers=headers)
    if response.status_code == 200:
        res = response.json()
    intents_rankings = res.get('intent_ranking')
    intents = []
    for intent in intents_rankings:
        if intent.get('confidence') > 0.3:
            intents.append(intent['name'])
    return intents


def get_review_actual_intent(review):
    actual_reply = review.reply.replied_text
    for c_r in replies:
        replied_text = c_r.reply
        similarity = SequenceMatcher(None, actual_reply, replied_text).ratio()
        if similarity > 0.7:
            return c_r.reply_category
    return None


def do_predict_correctly(review, actual_intent):
    intents = model_inference(review.comment)
    return 1 if actual_intent in intents else 0


def get_review_report_of_nth_days(days):
    date = timezone.now() - timezone.timedelta(days=days)
    reviews = Review.objects.filter(create_time__gte=date, star_rating__gte=4).exclude(comment=None)

    # Write report into a csv
    with open('review_report.csv', 'w') as file:
        header_row = ['review', 'reply', 'model_inference', 'actual_class', 'classified']
        writer = csv.writer(file)
        writer.writerow(header_row)
        for review in reviews:
            review_text = review.comment
            reply = review.reply.replied_text
            model_pred = model_inference(review_text)
            actual_class = get_review_actual_intent(review)
            classified = do_predict_correctly(review, actual_class)
            row = [review_text, reply, model_pred, actual_class, classified]
            writer.writerow(row)