from datetime import datetime
from xml.etree import cElementTree as eTree
from typing import Optional

from sysactions import (
    StopAction,
    show_messagebox,
)


datetime_format = "%Y-%m-%dT%H:%M:%S.%f"


def _get_last_stored_state(
    order_picture,    # type: eTree.Element
):
    # type: (...) -> Optional[datetime]

    stored_states = order_picture.findall(".//StateHistory/State[@state='STORED']")
    if not stored_states:
        return None

    return datetime.strptime(
        stored_states[-1].get("timestampGMT"),
        datetime_format,
    )


def validate_can_change_order(
    pos_id,                 # type: str
    order_picture,          # type: eTree.Element
    line_to_replace,        # type: str
    context,                # type: str
    line_number,            # type: str
    sale_type=None,         # type: Optional[str]
):
    # type: (...) -> None

    sale_type = order_picture.get("saleTypeDescr") if not sale_type and order_picture else sale_type
    if sale_type != "DRIVE_THRU":
        return

    last_stored_datetime = _get_last_stored_state(order_picture=order_picture)
    if last_stored_datetime is None:
        return

    sale_line_last_updated = None
    for sale_line in order_picture.findall(".//SaleLine"):
        is_line_change = _check_if_is_trying_to_change_line(
            sale_line=sale_line,
            line_number=line_number,
            line_to_replace=line_to_replace,
            context=context,
        )
        adding_modifier = _is_adding_modifier(
            sale_line=sale_line,
            context=context,
            line_number=line_number,
        )
        if is_line_change or adding_modifier:
            sale_line_last_updated = datetime.strptime(
                sale_line.get("createdAt"),
                datetime_format,
            )
            break

    if sale_line_last_updated and sale_line_last_updated <= last_stored_datetime:
        show_messagebox(
            posid=pos_id,
            message="$CANNOT_CHANGE_DRIVE_OPENED_ORDER",
            icon="error",
        )
        raise StopAction()


def _is_adding_modifier(
    sale_line,      # type: eTree.Element,
    context,        # type: str
    line_number,    # type: str
):
    # type: (...) -> bool

    line_item_id = "{}.{}".format(
        sale_line.get("itemId"),
        sale_line.get("partCode"),
    )
    return line_item_id in context and line_number == sale_line.get("lineNumber")


def _check_if_is_trying_to_change_line(
    sale_line,          # type: eTree.Element
    line_number,        # type: str
    line_to_replace,    # type: str
    context,            # type: str
):
    # type: (...) -> bool

    abs_item_id = "{}.{}".format(
        sale_line.get("itemId"),
        sale_line.get("partCode"),
    )
    is_item_replace = line_to_replace == abs_item_id and line_number == sale_line.get("lineNumber")

    same_line_number = line_number == sale_line.get("lineNumber")
    is_option_or_can_add = sale_line.get("itemType") in ["OPTION", "CANADD", "INGREDIENT"]
    is_item_add = not line_to_replace and context == abs_item_id and is_option_or_can_add and same_line_number

    return is_item_replace or is_item_add
