from typing import (
    Any,
    Dict,
    List,
)

from ._ItemType import ItemType
from ._UpdatableEntity import UpdatableEntity


class SaleLine(UpdatableEntity):
    def __init__(
        self,
        sale_line_id: int,
        line_number: int,
        context: str,
        part_code: int,
        level: int,
        name: str,
        item_type: ItemType,
        multiplied_qty: float,
        qty: float,
        default_qty: int,
        unit_price: float,
        added_unit_price: float,
        item_price: float,
        item_discount: float,
        item_tax: float,
        custom_properties: Dict[str, Any],
        tags: Dict[str, str],
    ):
        self.sale_line_id = sale_line_id
        self.line_number = line_number
        self.context = context
        self.part_code = part_code
        self.level = level
        self.name = name
        self.item_type = item_type
        self.multiplied_qty = multiplied_qty
        self.qty = qty
        self.default_qty = default_qty
        self.unit_price = unit_price
        self.added_unit_price = added_unit_price
        self.item_price = item_price
        self.item_discount = item_discount
        self.item_tax = item_tax
        self.custom_properties = custom_properties
        self.tags = tags
        
        self.sons: List["SaleLine"] = []

    @classmethod
    def create_from_dict(cls, record: dict):
        tags = {}
        if "tags" in record:
            str_tags = record["tags"]
            for str_tag in str_tags:
                tag_key, tag_value = str_tag.split("=")
                tags[tag_key] = tag_value

        sale_line = cls(
            sale_line_id=record["id"],
            line_number=int(record["lineNumber"]),
            context=record["itemId"],
            part_code=record["partCode"],
            level=record["level"],
            name=record["name"],
            item_type=ItemType(record["itemType"]),
            multiplied_qty=record["multipliedQty"],
            qty=record["qty"],
            default_qty=record.get("defaultQty", 0),
            unit_price=record["unitPrice"],
            added_unit_price=record["addedUnitPrice"],
            item_price=record["itemPrice"],
            item_discount=record.get("itemDiscount", 0.0),
            item_tax=record.get("itemTax", 0.0),
            custom_properties=record.get("customProperties", {}),
            tags=tags,
        )
        return sale_line

    @classmethod
    def create_list_from_list(cls, records: List[dict]):
        ret = []
        for record in records:
            ret.append(cls.create_from_dict(record=record))

        return ret

    def update(self, new_data: 'SaleLine'):
        self.line_number = new_data.line_number
        self.context = new_data.context
        self.part_code = new_data.part_code
        self.level = new_data.level
        self.name = new_data.name
        self.item_type = new_data.item_type
        self.multiplied_qty = new_data.multiplied_qty
        self.qty = new_data.qty
        self.default_qty = new_data.default_qty
        self.unit_price = new_data.unit_price
        self.added_unit_price = new_data.added_unit_price
        self.item_price = new_data.item_price
        self.item_discount = new_data.item_discount
        self.item_tax = new_data.item_tax
        self.custom_properties = new_data.custom_properties
        self.tags = new_data.tags

    def __id__(self):
        return self.sale_line_id

    @property
    def item_id(self):
        return f"{self.context}.{self.part_code}"

    def add_son(self, sale_line: "SaleLine"):
        self.sons.append(sale_line)
        self.sons = sorted(self.sons, key=lambda son: son.part_code)

    def __str__(self):
        return f"{self.line_number}.{self.context}.{self.part_code}: {self.multiplied_qty:.2f}x{self.name}"

    def __repr__(self):
        return self.__str__()
