import logging

from application.interactor.get_coupons_on_payment.dto import GetBenefitOnPaymentRequest
from application.model import (
    BenefitAutomaticTypes,
    ApplierSubTypes,
)
from application.repository.api import APIRepository
from typing import (
    Any,
    Optional,
    Dict,
)

logger = logging.getLogger(__name__)


class GetBenefitOnPaymentInteractor(object):
    def __init__(
        self,                       # type: GetBenefitOnPaymentInteractor
        api_repository,             # type: APIRepository
        partner_has_endpoint,       # type: bool
    ):
        # type: (...) -> None

        self.api_repository = api_repository
        self.partner_has_endpoint = partner_has_endpoint

    def get_benefit_on_payment(
        self,       # type: GetBenefitOnPaymentInteractor
        request,    # type: GetBenefitOnPaymentRequest
    ):
        # type: (...) -> Optional[Dict]

        if not self.partner_has_endpoint:
            return None

        response = self.api_repository.get_benefit_on_payment(
            pos_id=request.pos_id,
            loyalty_customer_id=request.loyalty_customer_id,
            payment_info={
                "tenderId": request.payment_info.tender_id,
                "tenderAmount": request.payment_info.tender_amount,
                "tenderDesc": request.payment_info.tender_desc,
                "tenderType": request.payment_info.tender_type,
                "changeAmount": request.payment_info.change_amount,
            },
        )

        if response is None:
            return None

        filtered = self._filter_benefit_by_automatic_on_payment(benefit=response)
        benefit = self._filter_by_valid_actions(benefit=filtered)
        if benefit:
            self._set_tender_info_into_benefit_action(
                benefit=benefit,
                loyalty_id=request.loyalty_customer_id,
            )
            benefit["applier"] = "Loyalty"
            benefit["applierSubType"] = ApplierSubTypes.PAYMENT

        return benefit

    @staticmethod
    def _filter_benefit_by_automatic_on_payment(
        benefit,    # type: Dict
    ):
        # type: (...) -> Optional[Dict]

        if benefit.get("automatic") is None:
            benefit["automatic"] = BenefitAutomaticTypes.ON_PAYMENT

        if benefit.get("automatic") != BenefitAutomaticTypes.ON_PAYMENT:
            return None

        return benefit

    def _filter_by_valid_actions(
        self,           # type: GetBenefitOnPaymentInteractor
        benefit,        # type: Dict[str, Any]
    ):
        # type: (...) -> Optional[Dict]

        action = self._get_action(benefit=benefit)
        if not action:
            return None

        valid_action_names = ("paymentAmount", "discountAmountOnTotal")
        for action_name in valid_action_names:
            if action_name in action:
                return benefit

        return None

    def _set_tender_info_into_benefit_action(
        self,          # type: GetBenefitOnPaymentInteractor
        benefit,       # type: Dict[str, Any]
        loyalty_id,    # type: str
    ):
        # type: (...) -> None

        action = self._get_action(benefit=benefit)
        if "paymentAmount" in action:
            action["paymentAmount"][0]["tenderInfo"] = {
                "loyaltyId": loyalty_id,
            }

    def _get_action(
        self,      # type: GetBenefitOnPaymentInteractor
        benefit,   # type: Dict[str, Any]
    ):
        # type: (...) -> Optional[Dict]

        if benefit is None or len(benefit["actions"]) > 1:
            return None

        return self._get_first_key_value(benefit["actions"])

    @staticmethod
    def _get_first_key_value(
        the_dict,       # type: Dict
    ):
        # type: (...) -> Dict

        return the_dict[the_dict.keys()[0]]

