from logging import Logger

from application.model.benefit import ActionResult
from posot import OrderTaker

from messagebus import MessageBus
from typing import Dict

from application.model.order import Order
from application.model.transactions import AddBenefitToApplyUnitOfWork
from application.model.benefit import ActionTypes, Action
from application.model.conditions import Restrictions

from ._DiscountService import DiscountService
from ._OrderService import OrderService


class ActionService(object):
    def __init__(
        self,
        order_service,      # type: OrderService
        product_groups,     # type: Dict
        message_bus,        # type: MessageBus
        logger,             # type: Logger
    ):
        # type: (...) -> None

        self.message_bus = message_bus
        self.order_service = order_service
        self.product_groups = product_groups
        self.logger = logger

    def apply_action(self, action, burnt_items, uow, pos_ot, restriction, on_total):
        # type: (Action, Dict, AddBenefitToApplyUnitOfWork, OrderTaker, Restrictions, bool) -> ActionResult

        order = self.order_service.get_order(uow.pos_id, order_picture=uow.order.order_picture)
        discount_ids = Order.get_available_discount_ids(pos_ot)
        service = DiscountService(
            pos_ot=pos_ot,
            product_groups=self.product_groups,
            message_bus=self.message_bus,
            logger=self.logger,
        )
        result = ActionResult([], {}, [], {}, False, False)

        if order.order_state == "TOTALED":
            if action.name == ActionTypes.discountAmountOnTotal.value:
                result = service.apply_discount_amount_on_total(action, order, restriction, discount_ids)

            if action.name == ActionTypes.discountPercentageOnTotal.value:
                result = service.apply_discount_percentage_on_total(
                    action=action,
                    order=order,
                    restriction=restriction,
                    available_discount_ids=discount_ids,
                    benefit=uow.benefit,
                )

            if action.name == ActionTypes.discountAmountByItems.value:
                result = service.apply_discount_amount_by_items(action, order, restriction, discount_ids, False)

            if action.name == ActionTypes.discountAmountByItemsOnTotal.value:
                result = service.apply_discount_amount_by_items(action, order, restriction, discount_ids, True)

            if action.name == ActionTypes.discountPercentageByItems.value:
                result = service.apply_discount_percentage_by_items(action, order, restriction, discount_ids, False)

            if action.name == ActionTypes.discountPercentageByGroupsOnTotal.value:
                result = service.apply_discount_percentage_by_groups(action, order, restriction, discount_ids, True)

            if action.name == ActionTypes.discountAmountByGroupsOnTotal.value:
                result = service.apply_discount_amount_by_groups(action, order, restriction, discount_ids, True)

            if action.name == ActionTypes.discountPercentageByItemsOnTotal.value:
                result = service.apply_discount_percentage_by_items(action, order, restriction, discount_ids, True)

            if action.name == ActionTypes.paymentAmount.value:
                result = service.apply_discount_amount_on_total_by_tender(action, order, restriction)

            if action.name == ActionTypes.paymentPercentage.value:
                result = service.apply_discount_percentage_on_total_by_tender(action, order, restriction)

            if action.name == ActionTypes.paymentAmountOnItem.value:
                result = service.apply_discount_amount_on_total_by_tender(action, order, restriction, True)

            if action.name == ActionTypes.itemsToAdd.value:
                result = service.apply_tender_on_added_items(action, order, uow.benefit_order_info)

            if result.benefit_applied:
                result.items_to_burn = order.get_items_to_burn(order, uow.benefit, burnt_items, self.product_groups)

            return result

        elif order.order_state == "IN_PROGRESS":
            if action.name == ActionTypes.itemsToAdd.value:
                return service.apply_items_to_add(
                    action=action,
                    burnt_items=burnt_items,
                    uow=uow,
                    restriction=restriction,
                    on_total=on_total,
                )

            if on_total is False:
                result.items_to_burn = order.get_items_to_burn(order, uow.benefit, burnt_items, self.product_groups)
                result.pending_to_apply = True
                return result

        return ActionResult([], {}, [], {}, False, False)
