from typing import List, Optional

import persistence
from msgbus import MBEasyContext
from pos_model import OrderKey, PosConnection
from _ModuleLogger import logger


class OrderRepository(object):
    def __init__(self, mbcontext, pos_list):
        # type: (MBEasyContext, list) -> None
        self.mbcontext = mbcontext
        self.pos_list = pos_list

    def get_all_orders_to_disable(self):
        # type: () -> List[OrderKey]

        void_state_id = 4
        orders_to_disable = []  # type: List[OrderKey]

        for pos_id in self.pos_list:  # type: int
            pos_connection = None  # type: Optional[PosConnection]

            try:
                pos_connection = persistence.Driver().open(self.mbcontext, dbname=str(pos_id))
                cursor = pos_connection.select("""
                    SELECT o.OrderId
                    FROM Orders o
                    INNER JOIN OrderCustomProperties ocp_include ON o.OrderId = ocp_include.OrderId
                    AND ocp_include.key = 'FISCAL_ID'
                    LEFT JOIN OrderCustomProperties ocp_exclude ON o.OrderId = ocp_exclude.OrderId
                    AND ocp_exclude.key in ('ORDER_DISABLED', 'CANCELED_AFTER_PAID')
                    WHERE ocp_exclude.OrderId IS NULL
                      AND o.StateId = {0}
                    ORDER BY o.OrderId DESC
                    LIMIT 100
                """.format(void_state_id))

                if cursor and cursor.rows() > 0:
                    for row in cursor:
                        order_id = row.get_entry(0)
                        orders_to_disable.append(OrderKey(pos_id=str(pos_id), order_id=order_id))

            except Exception as _:
                logger.exception("Error getting orders to disable from pos [{}]".format(pos_id))
            finally:
                if pos_connection:
                    pos_connection.close()

        return orders_to_disable

    def mark_order_disabled(self, pos_id, order_id):
        pos_connection = None
        try:
            pos_connection = persistence.Driver().open(self.mbcontext, dbname=str(pos_id))
            self._insert_order_disabled(pos_connection, order_id, "true")
        except Exception as _:
            logger.exception("Erro marcando order como disabled")
        finally:
            if pos_connection:
                pos_connection.close()

    def mark_order_canceled(self, pos_id, order_id):
        pos_connection = None
        try:
            pos_connection = persistence.Driver().open(self.mbcontext, dbname=str(pos_id))
            self._insert_order_canceled(pos_connection, order_id, "true")
        except Exception as _:
            logger.exception("Erro marcando order como cancelada")
        finally:
            if pos_connection:
                pos_connection.close()

    def mark_order_not_disabled(self, pos_id, order_id):
        pos_connection = None
        try:
            pos_connection = persistence.Driver().open(self.mbcontext, dbname=str(pos_id))
            self._insert_order_disabled(pos_connection, order_id, "false")
        except Exception as _:
            logger.exception("Erro marcando order como 'nao inutilizada'")
        finally:
            if pos_connection:
                pos_connection.close()

    @staticmethod
    def _insert_order_disabled(pos_connection, order_id, value):
        pos_connection.query("""INSERT INTO OrderCustomProperties (OrderId, Key, Value) VALUES ({0:s}, "ORDER_DISABLED", "{1:s}")""".format(order_id, value))

    @staticmethod
    def _insert_order_canceled(pos_connection, order_id, value):
        pos_connection.query("""INSERT INTO OrderCustomProperties (OrderId, Key, Value) VALUES ({0:s}, "CANCELED_AFTER_PAID", "{1:s}")""".format(order_id, value))
