# -*- coding: utf-8 -*-
import logging
from datetime import datetime, timedelta
from xml.etree import cElementTree as eTree

from sysactions import get_model, get_business_period, get_cfg, is_day_opened, has_current_order
from systools import sys_log_exception

from check_table_status import has_tab_or_tables_opened
from typing import Optional

pos_block_hour = {}
pos_datetime_to_block_pos = {}

logger = logging.getLogger("TableActions")


def pos_must_be_blocked(pos_id):
    # type: (str) -> bool

    try:
        model = get_model(pos_id)
        if not pos_need_to_be_blocked(pos_id, model):
            return False

        if has_current_order(model):
            return False

        login_mode = model.find("WorkingMode").get("usrCtrlType")
        pod_type = model.find("WorkingMode").get("podType")

        if not _pos_serves_table(pod_type, pos_id):
            return True

        if login_mode == "QSR":
            return _logged_user_has_no_open_table(pos_id)
        else:
            return _all_tables_are_closed(pos_id)

    except Exception as _:
        sys_log_exception("Error verifying if POS {} must be blocked".format(pos_id))

    return False


def pos_need_to_be_blocked(pos_id, model=None):
    # type: (str, Optional[eTree.XML]) -> bool

    try:
        if model is None:
            model = get_model(pos_id)

        if pos_id not in pos_block_hour:
            pos_block_hour[pos_id] = int(get_cfg(pos_id).key_value("hourToBlockPos", "0"))

        if pos_id in pos_datetime_to_block_pos:
            datetime_to_block_pos = pos_datetime_to_block_pos[pos_id]
        else:
            hour_to_block_pos = pos_block_hour[pos_id]
            period = get_business_period(model)

            if period == '0' or not is_day_opened(model):
                return False

            datetime_to_block_pos = datetime(int(period[:4]), int(period[4:6]), int(period[6:8]))
            datetime_to_block_pos += timedelta(days=1)
            datetime_to_block_pos += timedelta(hours=hour_to_block_pos)

        current_date = datetime.now()
        if current_date > datetime_to_block_pos:
            if pos_id in pos_datetime_to_block_pos:
                pos_datetime_to_block_pos.pop(pos_id, None)

            return True
        else:
            pos_datetime_to_block_pos[pos_id] = datetime_to_block_pos
    except Exception as _:
        sys_log_exception("Error verifying if POS {} must be blocked".format(pos_id))

    return False


def _pos_serves_table(pod_type, pos_id=None):
    # type: (str, Optional[int]) -> bool

    return pod_type not in ["FC", "TT", "DL"] and pos_id != 0


def _logged_user_has_no_open_table(pos_id):
    # type: (str) -> bool

    model = get_model(pos_id)
    period = get_business_period(model)
    operator = model.find("Operator")
    if operator is None:
        return False

    user_id = operator.get("id")
    return not has_tab_or_tables_opened(period, pos_id, user_id)


def _all_tables_are_closed(pos_id):
    # type: (str) -> bool

    model = get_model(pos_id)
    period = get_business_period(model)

    return not has_tab_or_tables_opened(period, pos_id)
