import logging
from datetime import datetime, timedelta
from threading import Lock

from sysactions import action
from application.interactor import NDiscountInteractor
from typing import List, Dict
from actions.coupon.get_coupon import is_coupon_component_connected

discounts_cache = []
discounts_available_cache = False
coupons_available_cache = False
last_cache_time = None
lock = Lock()
logger = logging.getLogger("PosActions")


@action
def is_discounts_available(pos_id, seconds_to_renew_cache=3600):
    global discounts_available_cache
    global coupons_available_cache

    get_visible_discounts(pos_id, seconds_to_renew_cache=seconds_to_renew_cache)
    if len(discounts_cache) > 0:
        discounts_available_cache = True
    else:
        discounts_available_cache = False

    return str(discounts_available_cache).lower()


def get_visible_discounts(pos_id, seconds_to_renew_cache=3600):
    global last_cache_time
    global discounts_cache
    global discounts_available_cache

    with lock:
        now = datetime.now()
        seconds_to_renew = _get_seconds_to_renew(seconds_to_renew_cache)
        component_connected = is_coupon_component_connected(pos_id)
        if not discounts_cache or _reached_seconds_to_renew_cache(now, seconds_to_renew):
            if not component_connected:
                discounts_cache = _get_static_discounts()
            else:
                discounts_cache = _get_discounts_from_database(pos_id, True)
            last_cache_time = now
        return discounts_cache, not component_connected


def _get_discounts_from_database(pos_id, only_visible):
    # type: (int, bool) -> List[Dict[str, any]]

    discount_interactor = NDiscountInteractor()
    coupons = discount_interactor.get_benefits(pos_id, only_visible)

    discounts = []
    for item in coupons:
        benefit_id = str(item.get("benefitId", ""))
        coupon = item.get("benefitJson", {})
        name = coupon.get("userDescription", "")
        discounts.extend([{"coupon": coupon,
                           "index": coupon.get("priority", 0),
                           "name": name,
                           "benefit_id": benefit_id}]
                         )
    discounts = sorted(discounts, key=lambda element: element["index"])
    for index, d in enumerate(discounts):
        d["index"] = index + 1

    return discounts


def _get_seconds_to_renew(seconds_to_renew_cache):
    seconds_to_renew = 180
    try:
        seconds_to_renew = int(seconds_to_renew_cache)
    except TypeError as _:
        pass
    return seconds_to_renew


def _reached_seconds_to_renew_cache(now, seconds_to_renew_cache):
    return not last_cache_time or now > last_cache_time + timedelta(seconds=seconds_to_renew_cache)


def _get_static_discounts():
    coupons = [{"benefit_id": 1, "name": 'Valor', "index": 1}, {"benefit_id": 2, "name": 'Porcentagem', "index": 2}]
    return coupons
