from application.service import OrderService, BenefitService
from application.model import Configurations
from typing import Dict, List, Optional


class OnOrderReopenInteractor(object):

    def __init__(self, configs, order_service, benefit_service):
        # type: (Configurations, OrderService, BenefitService) -> None

        self.configs = configs
        self.order_service = order_service
        self.benefit_service = benefit_service

    def execute(self, pos_id):
        # type: (int) -> None

        order_picture = self.order_service.get_order_picture(pos_id)

        state = order_picture.get("state", "") if order_picture else ""
        if state != "IN_PROGRESS":
            return

        order = self.order_service.get_order(pos_id, order_picture=order_picture)
        order_picture = order.order_picture
        remove_manual = order.table_id is None

        applied_benefits = self.order_service.get_applied_benefits_from_order_picture(pos_id, order_picture)
        if not applied_benefits:
            return

        benefits_to_remove = self._get_benefits_to_remove(applied_benefits)
        if len(benefits_to_remove) > 0:
            self.benefit_service.remove_benefits(pos_id, benefits_to_remove, order_picture, delete_manual=remove_manual)

        self.benefit_service.unset_applied_benefit(pos_id, ["IN_PROGRESS"])

    def _get_benefits_to_remove(self, applied_benefits):
        # type: (List) -> List

        benefits_to_remove = []
        for applied_benefit in applied_benefits:
            benefit_key_to_remove = self._get_benefit_id_to_remove(applied_benefit)
            if benefit_key_to_remove:
                benefits_to_remove.append(benefit_key_to_remove)

        return benefits_to_remove

    @staticmethod
    def _get_benefit_id_to_remove(applied_benefit):
        # type: (Dict) -> Optional[int]

        benefit_applied = applied_benefit.get("benefit_applied")
        if not benefit_applied:
            return None

        benefit = applied_benefit.get("benefit", {})
        added_sale_lines = len(applied_benefit.get("added_sale_lines")) > 0

        must_remove_added_line = benefit.get("automatic", "") not in ("ON_SALE", "ON_TABLE_OPEN")
        if added_sale_lines and not must_remove_added_line:
            return None

        return applied_benefit.get("benefit_key")
