# -*- coding: utf-8 -*-

import logging
from xml.etree.ElementTree import Element
from xml.etree import cElementTree as eTree

from msgbus import (
    TK_SLCTRL_OMGR_CLEARTENDERS,
    FM_PARAM,
    TK_SYS_ACK,
    MBMessage,
)

from actions import mb_context
from sysactions import (
    translate_message,
    get_model,
    send_message,
    get_posot,
    get_current_order,
)
from typing import (
    List,
    Optional,
    Tuple,
)

from application.repository import OrderRepository


class OrderInteractor(object):
    def __init__(self, pos_id):
        # type: (str) -> None

        self.logger = logging.getLogger("PosActions")
        self.order_repository = OrderRepository(mb_context)
        self.model = get_model(pos_id)
        self.pos_id = pos_id

    def get_orders_benefit(self, initial_date, end_date, operator_id):
        # type: (str, str, Optional[str]) -> List

        from msgbusboundary import MsgBusTableService as tableService
        try:
            all_coupons = translate_message(self.model, "ALL_COUPONS")
            pos_list = sorted(tableService().get_exclusive_pos_list())
            result = {'All': {'index': 0, 'id': None, 'name': all_coupons}}
            benefits = self.order_repository.get_orders_benefit(initial_date, end_date, operator_id, pos_list)
            index = 1
            for benefit in benefits:
                benefit_detail = benefit["benefit"]
                benefit_id = benefit_detail.get("id")
                if benefit_id in result.keys():
                    continue
                name = benefit_detail.get("userDescription").encode('utf-8')
                key = benefit_detail.get("name").encode('utf-8')
                data = {'index': index, 'id': benefit_id, 'name': name, 'key': key}
                result[benefit_id] = data
                index += 1

            return sorted(result.values(), key=lambda k: k['index'])
        except (Exception,):
            self.logger.exception("Error getting orders benefit")
            return []

    def get_fiscalized_orders(
            self,
            from_date,  # type: str
            pos_list,  # type: List[int]
    ):
        # type: (...) -> List

        return self.order_repository.get_fiscalized_orders(
            from_date=from_date,
            pos_list=pos_list,
        )

    def clear_order_tender(
        self,
        order_tender_id,            # type: str
        order_id,                   # type: str
        blk_notify="0",             # type: str
        tender_id="",               # type: str
        keep_tender_records="0",    # type: str
    ):
        # type: (...) -> None

        self.logger.info("Cleaning order tender. {}#{}. TenderId: {}".format(order_tender_id, order_id, tender_id))

        params = (
            blk_notify,
            self.pos_id,
            tender_id,
            order_tender_id,
            keep_tender_records,
            order_id
        )

        response = self.send_order_message(
            params=params,
            token=TK_SLCTRL_OMGR_CLEARTENDERS,
        )

        if response.token != TK_SYS_ACK:
            params = response.data.split('\0')
            self.logger.error("Error clear order tender: {} - {} - {}", params[0], params[0], params[1])

    def get_order_picture(
        self,
        pos_id=None,                # type: Optional[str]
        order_id="",                # type: Optional[str]
        use_order_id_model=True,    # type: Optional[bool]
    ):
        # type: (...) -> Optional[Element]

        pos_id = self.pos_id if pos_id is None else pos_id

        model = get_model(posid=pos_id)
        pos_ot = get_posot(model=model)

        if use_order_id_model is None:
            current_order = get_current_order(model=model)
            order_id = current_order.get("orderId")

        return eTree.XML(
            pos_ot.orderPicture(
                posid=pos_id,
                orderid=order_id,
            )
        )

    def get_order_from_order_picture(
        self,                           # type: OrderInteractor
        pos_id=None,                    # type: Optional[str]
        order_id="",                    # type: Optional[str]
        use_order_id_model=True,        # type: Optional[bool]
    ):
        # type: (...) -> Element

        order_picture = self.get_order_picture(
            pos_id=pos_id,
            order_id=order_id,
            use_order_id_model=use_order_id_model
        )
        return order_picture.find("Order") if order_picture.find("Order") else order_picture

    def send_order_message(
        self,
        params,     # type: Tuple
        token,      # type: int
    ):
        # type: (...) -> MBMessage

        params = "\0".join(str(p) for p in params)

        return send_message(
            dest_name="ORDERMGR%d" % int(self.pos_id),
            token=token,
            format=FM_PARAM,
            data=params,
            timeout=1000000 * 120
        )

    def get_pos_order_picture(
        self,  # type:  OrderInteractor
    ):
        order_interactor = OrderInteractor(
            pos_id=self.pos_id,
        )
        return order_interactor.get_order_from_order_picture(
            pos_id=self.pos_id
        )

    def is_order_in_progress(
        self,       # type:  OrderInteractor
    ):
        # type (...) -> bool

        current_order = self.get_pos_order_picture()
        return current_order.get("state") == "IN_PROGRESS"
