from logging import Logger

from model.config import Config
from model.repository import PosRepositoryModel
from model.services import (
    CouponServiceModel,
    OrderServiceModel
)
from model.error_type import PosValidationErrorsType
from model.exception import ValidationError
from interactor.route.order.apply_coupon.dto import ApplyCouponRequest
from validation_util import check_if_pos_id_is_valid, validate_api_key, check_if_order_is_in_progress_or_totaled
from posot import OrderTaker
from typing import Optional

FREE_COUPON_DATA = 'FREE_COUPON_DATA'


class ApplyCouponInteractor(object):
    def __init__(
            self,
            logger,             # type: Logger
            config,             # type: Config
            pos_repository,     # type: PosRepositoryModel
            coupon_service,     # type: CouponServiceModel
            order_service       # type: OrderServiceModel
    ):
        # type: (...) -> None

        self.logger = logger
        self.config = config
        self.pos_repository = pos_repository
        self.coupon_service = coupon_service
        self.order_service = order_service
        self.model = None
        self.pos_ot = None  # type: Optional[OrderTaker]
        self.price_list = None

    def execute(self, request):
        # type: (ApplyCouponRequest) -> None

        pos_id = validate_api_key(request, self.config.api_key_mapping)
        check_if_pos_id_is_valid(self.pos_repository, pos_id)

        coupon_data, coupon_applied = self.pos_repository.apply_coupon(
            pos_id=pos_id,
            coupon_code=request.coupon_code
        )

        self.model = self.pos_repository.get_model(pos_id)
        self.pos_ot = self.pos_repository.get_pos_ot(self.model)
        self.price_list = self.pos_repository.get_price_list(self.model)

        if self.pos_repository.has_current_order(self.model):
            check_if_order_is_in_progress_or_totaled(self.pos_repository, self.model)

        if coupon_applied:
            self.logger.info("Success coupon applied. CouponData: {}".format(coupon_data))
            order = self.pos_repository.get_current_order(self.model)
            order_id = order.get('orderId')
            order = self.pos_repository.get_order_details(
                pos_id=pos_id,
                order_id=order_id,
                pos_ot=self.pos_ot
            )
            if order:
                coupon_data = self.order_service.convert_mw_order_to_order_detail(order)

            return coupon_data

        else:
            self.logger.info("Error applying coupon. CouponData: {}".format(coupon_data))
            raise ValidationError(PosValidationErrorsType.CannotApplyCoupon, coupon_data)
