from typing import Optional

from sysactions import (
    action,
    get_model,
    get_posot,
    show_messagebox,
    StopAction,
)
from systools import sys_log_exception
from application.interactor import OrderInteractor

from order_api.dto.exception import ProductInRupture
from actions.do_complete_option.drive_thru import validate_can_change_order
from utilfunctions import is_table_service


@action
def doModifier(
    pos_id,         # type: str
    item_id,        # type: str
    level,          # type: str
    part_code,      # type: str
    qty,            # type: str
    line_number,    # type: str
    mod_type="",    # type: Optional[str]
):
    # type: (...) -> None

    from posactions import is_changing_order

    try:
        model = get_model(posid=pos_id)

        if is_table_service(model=model) and is_changing_order(model=model):
            show_messagebox(pos_id, message="$CANNOT_ADD_ITEMS_IN_AN_OPENED_ORDER", icon="error")
            raise StopAction()

        abs_item_id = "{}.{}".format(
            item_id,
            part_code,
        )
        _validate_if_can_modify(
            pos_id=pos_id,
            item_id=abs_item_id,
            line_number=line_number,
        )

        _do_modify(
            pos_id=pos_id,
            model=model,
            item_id=item_id,
            level=level,
            part_code=part_code,
            qty=qty,
            line_number=line_number,
            mod_type=mod_type,
        )

    except ProductInRupture as ex:
        sys_log_exception("[change_modifier] Product {} in Rupture".format(ex.error_description))
        show_messagebox(
            posid=pos_id,
            message="$RUPTURED_PRODUCT|{}".format(ex.error_description),
        )


def _do_modify(
    pos_id,         # type: str
    model,          # type: str
    item_id,        # type: str
    level,          # type: str
    part_code,      # type: str
    qty,            # type: str
    line_number,    # type: str
    mod_type,       # type: str
):
    # type: (...) -> None

    from posactions import (
        get_next_level,
        change_modifier,
        get_order_sale_line,
        comment_map,
        remove_custom_comment,
        add_custom_comment,
    )

    pos_ot = get_posot(model=model)
    next_level = get_next_level(
        model=model,
        item_id=item_id,
        line_number=line_number,
        level=level,
    )
    removing = int(qty) == 0 or not mod_type
    order = change_modifier(
        pos_id=pos_id,
        line_number=line_number,
        item_id=item_id,
        level=next_level,
        part_code=part_code,
        new_qty=qty,
    )

    curr_line = get_order_sale_line(
        order=order,
        item_id=item_id,
        part_code=part_code,
        line_number=line_number,
    )
    line_exists = curr_line and len(curr_line) > 0

    comment_keys = comment_map.keys()
    if mod_type in comment_keys or removing:
        remove_custom_comment(
            pos_ot=pos_ot,
            curr_line=curr_line,
        )

        if not removing:
            if not line_exists:
                change_modifier(
                    pos_id=pos_id,
                    line_number=line_number,
                    item_id=item_id,
                    level=next_level,
                    part_code=part_code,
                    new_qty="0",
                )
                change_modifier(
                    pos_id=pos_id,
                    line_number=line_number,
                    item_id=item_id,
                    level=next_level,
                    part_code=part_code,
                    new_qty=qty,
                )

            add_custom_comment(
                pos_ot=pos_ot,
                item_id=item_id,
                part_code=part_code,
                line_number=line_number,
                level=str(next_level),
                comment=comment_map[mod_type],
            )


def _validate_if_can_modify(
    pos_id,         # type: str
    item_id,        # type: str
    line_number,    # type: str
):
    # type: (...) -> None

    order_interactor = OrderInteractor(pos_id=pos_id)
    order_picture = order_interactor.get_order_picture(pos_id=pos_id)
    if order_picture is None:
        return

    validate_can_change_order(
        pos_id=pos_id,
        order_picture=order_picture,
        line_to_replace="",
        context=item_id,
        line_number=line_number,
    )
