# -*- coding: utf-8 -*-

import json
import logging
from xml.etree.ElementTree import Element

from api.order import get_order_service
from typing import (
    Any,
    Dict,
    Optional,
    Tuple,
)

from sysactions import (
    action,
    show_any_dialog,
    StopAction,
)

from actions.delivery.delivery_address_information import (
    insert_or_update_customer,
    insert_or_update_customer_with_confirmation,
)
from custom_sysactions import block_action_if_there_is_no_order
from order_api.dto import CustomProperty

logger = logging.getLogger("PosActions")


def handle_customer_data_on_total(
    pos_id,         # type: str
    order_picture,  # type: Element
):
    # type: (...) -> None

    if order_picture.attrib["saleTypeDescr"] != "DELIVERY":
        return

    from posactions import ask_customer_delivery_data
    if ask_customer_delivery_data != "onTotal":
        return

    phone_property = order_picture.find('.//OrderProperty[@key="CUSTOMER_PHONE"]')
    if phone_property is not None and phone_property.attrib["value"] != "":
        return

    customer_data = request_and_save_customer_data(pos_id=pos_id)
    if customer_data is None:
        raise StopAction()

    _add_customer_data_properties_on_order(pos_id, order_picture, customer_data)


@action
@block_action_if_there_is_no_order
def edit_order_delivery_address(
    pos_id,         # type: str
):
    # type: (...) -> None

    customer_data = request_and_save_customer_data(pos_id=pos_id)
    if customer_data is None:
        return

    order = get_order_service(pos_id=pos_id).get_order_picture()
    _add_customer_data_properties_on_order(
        pos_id=pos_id,
        order=order,
        customer_data=customer_data,
    )


@action
def save_delivery_address(
    pos_id,     # type: str
):
    # type: (...) -> None

    if get_order_service(pos_id=pos_id).has_current_order():
        edit_order_delivery_address(pos_id=pos_id)
        return

    selected_option, customer_json = full_request_customer_data(
        pos_id=pos_id,
        dialog_type="saveCustomerDeliveryAddress",
    )
    if selected_option is None:
        return

    insert_or_update_customer(
        customer_json=customer_json,
    )

    if selected_option == 2:
        from posactions import do_start_order
        do_start_order(
            pos_id=pos_id,
            sale_type="DELIVERY",
            customer_data=customer_json,
        )


def request_and_save_customer_data(
    pos_id,                           # type: str
):
    # type: (...) -> Optional[Dict[str, Any]]

    customer_json = request_customer_data(pos_id=pos_id)
    if not customer_json:
        return None

    insert_or_update_customer_with_confirmation(
        pos_id=pos_id,
        customer_json=customer_json,
    )

    return customer_json


def request_customer_data(
    pos_id,     # type: str
):
    # type: (...) -> Optional[Dict[str, str]]

    _, customer_json = full_request_customer_data(
        pos_id=pos_id,
        dialog_type="deliveryAddress",
    )

    return customer_json


def full_request_customer_data(
    pos_id,             # type: str
    dialog_type,        # type: str
):
    # type: (...) -> Tuple[Optional[int], Optional[Dict[str, str]]]

    customer = show_any_dialog(
        posid=pos_id,
        dlgtype=dialog_type,
        message="",
        title="",
        infotext="",
        buttons="",
        icon="",
        timeout=6000000,
        mask="",
        defvalue="",
        minvalue="",
        maxvalue="",
        contents="",
        asynch=False,
    )
    customer_json = json.loads(customer)

    if not customer_json:
        return None, None

    selected_option = customer_json["SELECTED_OPTION"]
    customer_json.pop('SELECTED_OPTION')
    return selected_option, customer_json


def _add_customer_data_properties_on_order(
    pos_id,             # type: str
    order,              # type: Element
    customer_data,      # type: Dict[str, Any]
):
    # type: (...) -> None

    properties_to_add = []
    properties_to_remove = []
    for key, value in customer_data.items():
        if value is None and order.find('.//OrderProperty[@key="{}"]'.format(key)) is not None:
            properties_to_remove.append(key)
        else:
            properties_to_add.append(CustomProperty(
                key=key,
                value=value,
            ))

    order_service = get_order_service(pos_id=pos_id)
    if properties_to_add:
        order_service.set_order_custom_properties(custom_properties=properties_to_add)

    if properties_to_remove:
        order_service.remove_order_custom_properties(keys=properties_to_remove)
