from random import choice, choices
from datetime import date, timedelta
from flask import session, redirect, url_for, request, render_template
from sqlalchemy import desc
from share import share
from create_db import Card, Rating, get_session
from settings import get_settings
"""
testing
"""
def autofill_ratings():
    dbsession = get_session()
    for i in range(100):
        card = Rating(user_id="1", card_id="10", rating_value=choice(["Yes", "Maybe", "No"]), rating_time=date.today()-timedelta(choice([i for i in range(100)])))
        dbsession.add(card)
        dbsession.commit()
        dbsession.close()    
    return None

"""
Main fuctions
"""
def calculate_interval(sorted_rates):
    maybe_factor    = 1.2
    no_factor       = 2.1
    
    print(sorted_rates[0].rating_value)
    if sorted_rates == []:
        #this is a new card, but interval can't be zero cuz multiplication... may have to handeled differently
        return 1
    elif sorted_rates[0].rating_value == "Yes":
        return 1
    elif sorted_rates[0].rating_value == "Maybe":
        sorted_rates.pop(0)
        return calculate_interval(sorted_rates) * maybe_factor
    elif sorted_rates[0].rating_value == "No":
        sorted_rates.pop(0)
        return calculate_interval(sorted_rates) * no_factor
    elif sorted_rates[0].rating_value == "Delete":
        return "Deleted"


def get_interval(card_id):
    """
    takes card_id looks at the history of rates and gives the current interval
    """
    dbsession = get_session()
    sorted_rates_by_card = dbsession.query(Rating).filter(Rating.card_id == card_id).order_by(desc(Rating.rating_time)).all()
    if sorted_rates_by_card == None:
        print("ni kart... kaj zdaj") #@TODO
        return None
    else:
        interval = calculate_interval(sorted_rates_by_card)
        return round(interval)


def is_due(card_id):
    dbsession = get_session()
    interval = get_interval(card_id)
    
    last_rating_date = dbsession.query(Rating).filter(Rating.card_id == card_id).order_by(desc(Rating.rating_time)).first()
    due_date = last_rating_date.rating_time + timedelta(interval)
    
    return date.today() >= due_date


def list_of_due_card_by_ids(user_id):
    dbsession = get_session()
    cards = dbsession.query(Card).filter(Card.owner_id == user_id).all()
    l = []
    for card in cards:
        if is_due(card.id):
            l.append(card.id)
    return l


def list_of_new_cards_by_ids(user_id):
    dbsession = get_session()
    cards = dbsession.query(Card).filter(Card.owner_id == user_id).all()
    l = []
    for card in cards:
        rating = dbsession.query(Rating).filter(Rating.card_id == card.id).first()
        if rating == None:
            l.append(card.id)
    return l


def make_deck(user_id, max_new, max_due):
    due_cards = list_of_due_card_by_ids(user_id)
    new_cards = list_of_new_cards_by_ids(user_id)

    due_deck = []
    due_deck.append(choices(due_cards, k=max_due))  
    
    new_deck = []
    new_deck.append(choices(new_cards, k=max_new))
    
    deck = new_deck + due_deck
    return deck


def rated_today_by_staus (card_status):
    """
    Returns number of cards rated today by user by status (new or due)
    """
    dbsession = get_session()
    today = date.today()

    ratings_today = dbsession.query(Rating).filter(Rating.rating_time == today)
    n = 0
    d = 0
    for rating in ratings_today:
        count_all_rates_of_card = dbsession.query(Card).filter(Card.id == rating.card_id).count() 

        if count_all_rates_of_card == 1:
            n+=1
        elif count_all_rates_of_card > 1:
            d+=1
        else:
            print("wtf")
            raise Exception("Count be wrong! There should be at least one rating")
    
    if card_status == "new":
        return n
    elif card_status == "due":
        return d
    else:
        raise Exception("must input either 'new' or 'due' as parameter")


def get_a_card_by_status(card_status):
    if card_status == "new":
        l = list_of_new_cards_by_ids
        card_id = choice(list_of_due_card_by_ids)
    if card_status == "due":
        l = list_of_due_card_by_ids
        card_id = choice(list_of_due_card_by_ids)

    return card_id

"""
Engine
"""
def sr_session():
    dbsession = get_session()
    
    #check if user in session
    if not 'user_id' in session:
        redirect(url_for('login'))
    user_id = session['user_id']
    username = session['username']

    user_settings = get_settings(user_id)

    max_new = user_settings["max_new"]
    max_due = user_settings["max_due"]

    rated_today_new = rated_today_by_staus("new")
    rated_today_due = rated_today_by_staus("due")

    # Smo oddali obrazec?
    if request.method == 'POST':
        #get card_if from the card, rendered from the template, data actually from the template...
        card_id = request.form.get('card_id', None)
        if not card_id:
            raise Exception("card_id necesarry!")

        #this is the rendered card aka the card we are rating and submiting the data on
        if max_new - rated_today_new > 0:
            card_id=get_a_card_by_status("new")
        elif max_due - rated_today_due >0:
            card_id=get_a_card_by_status("due")
        

        submit_card = dbsession.query(Card).get(card_id)
        #@TODO check if this card is part of the user's deck to prevent possibile hack?

    # Share
        #Share button pressed? then reset the form - hence the if-else
        share_request = request.form.get("share", None)
        if share_request:
            # @TODO logika za share!
            share(submit_card, user_id)

    # Rate
        #If it's not a share it's a rate!
        else:
            rate = request.form.get('rate', None) #is this get somehow dangerous?
            
            if not rate:
                raise Exception("Need rate info!")

            r = Rating(user_id=user_id, card_id=card_id, rating_value=rate, rating_time=date.today())
            dbsession.add(r)
            dbsession.commit
            dbsession.close
  
    # Loudamo naslednjo karto v decku
    
    
    #TODO We need this but i don't know it's neccessay to distingush between submit/show
    show_card = card_id
        
    # Prikaži obrazec


    #Display from
    return render_template("deck.html", username=username, card=show_card)
