# -*- coding: utf-8 -*-
import iso8601
import json
import uuid

from xml.etree import cElementTree as eTree
from old_helper import convert_from_localtime_to_utc
from typing import Dict, List

from api.order import get_order_service
from order_api.dto import CustomProperty


def create_delivery_manual_order_json(
    pos_id,     # type: int
    xml_order,  # type: eTree.Element
):
    # type: (...) -> None

    name = _get_custom_property(
        xml_order=xml_order,
        custom_property="CUSTOMER_NAME",
    )
    phone = _get_custom_property(
        xml_order=xml_order,
        custom_property="CUSTOMER_PHONE",
    )
    document = _get_custom_property(
        xml_order=xml_order,
        custom_property="CUSTOMER_DOC",
    )
    state = _get_custom_property(
        xml_order=xml_order,
        custom_property="STATE",
    )
    city = _get_custom_property(
        xml_order=xml_order,
        custom_property="CITY",
    )
    neighborhood = _get_custom_property(
        xml_order=xml_order,
        custom_property="NEIGHBORHOOD",
    )
    reference = _get_custom_property(
        xml_order=xml_order,
        custom_property="ADDRESS_REFERENCE",
    )
    complement = _get_custom_property(
        xml_order=xml_order,
        custom_property="COMPLEMENT",
    )
    zip_code = _get_custom_property(
        xml_order=xml_order,
        custom_property="POSTAL_CODE",
    )
    number = _get_custom_property(
        xml_order=xml_order,
        custom_property="STREET_NUMBER",
    )
    street = _get_custom_property(
        xml_order=xml_order,
        custom_property="STREET_NAME",
    )
    need_logistics = _get_custom_property(
        xml_order=xml_order,
        custom_property="NEED_LOGISTICS",
    )
    pickup_type = _get_custom_property(
        xml_order=xml_order,
        custom_property="PICKUP_TYPE",
    )

    formatted_address = "{0}, {1} - {2} - {3}".format(street, number, neighborhood, city) if street and number else ""

    all_sale_lines = xml_order.findall("SaleLine")
    main_sale_lines = [x for x in all_sale_lines if x.get("level") == "0"]

    create_at = iso8601.parse_date(xml_order.get("createdAt", ""))
    create_at = convert_from_localtime_to_utc(localtime=create_at).strftime("%Y-%m-%d %H:%M:%S")
    order_id = xml_order.get("orderId", "-")
    remote_order_id = str(uuid.uuid4())
    manual_delivery_order_json = {
        "id": remote_order_id,
        "items": _get_items(
            all_sale_lines=all_sale_lines,
            sale_lines=main_sale_lines,
        ),
        "custom_properties": [
            {
                "key": "contact_number",
                "value": phone
            }, {
                "key": "customer_doc",
                "value": document
            }, {
                "key": "customer_name",
                "value": name
            }, {
                "key": "customer_phone",
                "value": phone
            }, {
                "key": "partner",
                "value": 'MANUAL'
            }, {
                "key": "created_at",
                "value": create_at
            }, {
                "key": "short_reference",
                "value": order_id
            }, {
                "key": "formatted_address",
                "value": formatted_address
            }, {
                "key": "street_name",
                "value": street
            }, {
                "key": "postal_code",
                "value": zip_code
            }, {
                "key": "need_logistics",
                "value": need_logistics
            }, {
                "key": "delivery_method",
                "value": 'DEFAULT'
            }, {
                "key": "logistic_integration_status",
                "value": 'Waiting'
            }, {
                "key": "pickup_type",
                "value": 'delivery'
            }, {
                "key": "manual_order_id",
                "value": remote_order_id
            },
        ],
        "pickup": {
            "type": pickup_type,
            "address": {
                "state": state,
                "city": city,
                "neighborhood": neighborhood,
                "reference": reference,
                "complement": complement,
                "postalCode": zip_code,
                "formattedAddress": formatted_address,
                "streetNumber": number,
                "streetName": street
            }
        },
        "totalPrice": float(xml_order.get("totalGross", 0)),
        "partner": "Delivery",
        "shortReference": xml_order.get("orderId", "-"),
        "subTotal": float(xml_order.get("totalGross", 0)),
        "createAt": xml_order.get("createdAt", "") + "Z"
    }

    all_custom_properties = _parse_custom_properties(parsed_json=manual_delivery_order_json)

    all_custom_properties.extend([
        CustomProperty(
            key="MANUAL_DELIVERY_ORDER_JSON",
            value=json.dumps(manual_delivery_order_json),
        ),
        CustomProperty(
            key="INTEGRATED_MANUAL_DELIVERY",
            value="TRUE",
        ),
        CustomProperty(
            key="REMOTE_ORDER_ID",
            value=remote_order_id,
        ),
    ])
    get_order_service(pos_id=pos_id).set_order_custom_properties(custom_properties=all_custom_properties)


def _parse_custom_properties(
    parsed_json,   # type: Dict[str, str]
):
    # type: (...) -> List[CustomProperty]

    all_custom_properties = []
    json_custom_properties = parsed_json.get("custom_properties") or []

    for json_custom_property in json_custom_properties:
        if json_custom_property["value"]:
            all_custom_properties.append(CustomProperty(
                key=json_custom_property["key"].upper(),
                value=json_custom_property["value"],
            ))

    return all_custom_properties


def _get_custom_property(
    xml_order,              # type: eTree
    custom_property,        # type: str
):
    # type: (...) -> str

    value = ""
    current_property = xml_order.find("CustomOrderProperties/OrderProperty[@key='{}']".format(custom_property))
    if current_property is not None:
        value = current_property.get("value", "").encode("utf-8")

    return value


def _get_items(
    all_sale_lines,     # type: List
    sale_lines,         # type: List
    level=0,            # type: int
):
    # type: (...) -> List

    items = []
    for sale_line in sale_lines:
        quantity = float(sale_line.get("multipliedQty", 0))
        if quantity == 0:
            continue

        line_number = sale_line.get("lineNumber")
        unit_price = float(sale_line.get("unitPrice", 0))
        overwritten_unit_price = float(sale_line.get("overwrittenUnitPrice", 0))
        price = (overwritten_unit_price or unit_price) * (quantity or 1)
        son_level = str(level + 1)
        son_item_id = sale_line.get("itemId") + "." + sale_line.get("partCode")
        child_sale_lines = [
            x for x in all_sale_lines
            if x.get("lineNumber") == line_number and x.get("level") == son_level and x.get("itemId") == son_item_id
        ]
        items.append(
            {
                "price": price,
                "parts": _get_items(
                    all_sale_lines,
                    child_sale_lines,
                    level + 1,
                ),
                "partCode": sale_line.get("partCode", ""),
                "observation": "",
                "quantity": quantity if sale_line.get("itemType", "") != "OPTION" else 1,
                "itemType": sale_line.get("itemType", "")
            }
        )

    return items
