import json
import logging

from typing import Optional

from actions.coupon.display_coupon import get_benefits_from_order
from application.interactor import OrderInteractor
from apply_loyalty_discount_on_payment import apply_loyalty_discount_on_payment
from actions.loyalty.model import LoyaltyStopPaymentAction
from posot import OrderTaker
from sysactions import (
    action,
    get_current_order,
    get_model,
    get_posot,
)

logger = logging.getLogger("PosActions")


@action
def apply_loyalty_before_payment(
    pos_id,             # type: str
    payment_amount,     # type: str
    tender,             # type: str
):
    # type: (...) -> str

    payment_amount = float(payment_amount or 0)
    model = get_model(posid=pos_id)
    pos_ot = get_posot(model=model)

    tender_info = json.loads(tender)
    order_picture = get_current_order(model=model)
    order_due_amount = float(order_picture.get("dueAmount"))

    try:
        loyalty_discount_data = apply_loyalty_discount_on_payment(
            pos_id=pos_id,
            tender_info=tender_info,
            payment_amount=payment_amount,
            order_due_amount=order_due_amount,
            order_taker=pos_ot,
        )

        if loyalty_discount_data is None:
            return "{}"
    except LoyaltyStopPaymentAction:
        return json.dumps({"cancel_payment": True})
    except (Exception,):
        logger.exception("Error checking for Loyalty on Payment")
        return "{}"

    benefit_key = _get_benefit_key(
        pos_id=pos_id,
        benefit_id=loyalty_discount_data.benefit_id,
        pos_ot=pos_ot,
    )

    if benefit_key:
        loyalty_discount_data.benefit_key = benefit_key

    return json.dumps(
        obj=loyalty_discount_data,
        default=vars,
    )


def _get_benefit_key(
    pos_id,        # type: str
    benefit_id,    # type: str
    pos_ot,        # type: OrderTaker
):
    # type: (...) -> Optional[str]

    if not benefit_id:
        return

    order = OrderInteractor(pos_id=pos_id).get_order_picture()
    benefit_list = get_benefits_from_order(
        pos_ot=pos_ot,
        order=order,
    )
    if not benefit_list:
        return

    benefit_key = None
    for benefit in benefit_list:
        if benefit.get('benefit').get('id') == benefit_id:
            benefit_key = benefit.get('benefit_key')
            break

    return benefit_key
