import json
from xml.etree import cElementTree as eTree

from product_api.dto import Part
from typing import (
    Dict,
    List,
)
from ._Order import Order
from ._SaleLine import SaleLine
from ._Tender import Tender
from ._CustomProperty import CustomProperty


def parse_order_custom_properties(
    order_xml,      # type: eTree.Element
):
    # type: (...) -> List[CustomProperty]

    custom_order_properties = order_xml.findall("CustomOrderProperties/OrderProperty")
    custom_properties = []    # type: List[CustomProperty]
    for custom_property in custom_order_properties:
        properties = custom_property.attrib
        if "key" not in properties:
            continue

        custom_properties.append(
            CustomProperty(
                key=properties.get("key"),
                value=properties.get("value"),
            )
        )

    return custom_properties


def parse_tenders(
    order_xml,      # type: eTree.Element
):
    # type: (...) -> List[Tender]

    tenders = order_xml.findall("TenderHistory/Tender")
    parsed_tenders = []     # type: List[Tender]
    for order_tender in tenders:
        parsed_tenders.append(
            Tender(
                tender_id=int(order_tender.get("tenderId", -1)),
                amount=float(order_tender.get("tenderAmount", 0))
            )
        )
    return parsed_tenders


def parse_sale_line_custom_properties(
    sale_line_xml,  # type: eTree.Element
):
    # type: (...) -> Dict[str, str]

    properties = sale_line_xml.get("customProperties")
    if not properties:
        return {}

    return json.loads(properties)


def parse_sale_line(
    sale_line_xml,  # type: eTree.Element
):
    # type: (...) -> SaleLine

    part = Part(
        part_code=int(sale_line_xml.get("partCode")),
        product_name=sale_line_xml.get("productName"),
        item_type=sale_line_xml.get("itemType"),
    )
    level = int(sale_line_xml.get("level") or 0)
    qty = float(sale_line_xml.get("qty") or 0) if level == 0 else float(sale_line_xml.get("multipliedQty") or 0)
    custom_properties = parse_sale_line_custom_properties(sale_line_xml=sale_line_xml)

    return SaleLine(
        line_number=int(sale_line_xml.get("lineNumber") or 0),
        part=part,
        level=level,
        item_id=sale_line_xml.get("itemId"),
        item_price=float(sale_line_xml.get("itemPrice") or 0),
        overwritten_unit_price=sale_line_xml.get("overwrittenUnitPrice"),
        quantity=qty,
        added_qty=float(sale_line_xml.get("addedQty") or 0),
        default_qty=int(sale_line_xml.get("defaultQty") or 0),
        comment=sale_line_xml.find("Comment"),
        custom_properties=custom_properties,
        discounts_applied=sale_line_xml.get("discountsApplied", None),
    )


def parse_order(
    order_xml,  # type: eTree.Element
):
    # type: (...) -> Order

    sale_lines_xml = order_xml.findall("SaleLine")
    sale_lines = []     # type: List[SaleLine]
    for sale_line in sale_lines_xml:
        sale_lines.append(parse_sale_line(sale_line_xml=sale_line))

    custom_properties = parse_order_custom_properties(order_xml=order_xml)

    tenders = parse_tenders(order_xml=order_xml)

    return Order(
        order_id=int(order_xml.get("orderId")),
        state=order_xml.get("state"),
        total_amount=float(order_xml.get("totalAmount") or 0),
        discount_amount=float(order_xml.get("discountAmount") or 0),
        total_after_discount=float(order_xml.get("totalAfterDiscount") or 0),
        total_tender=float(order_xml.get("totalTender") or 0),
        total_gross=float(order_xml.get("totalGross") or 0),
        sale_lines=sale_lines,
        custom_properties=custom_properties,
        tenders=tenders,
    )
