import datetime
from typing import (
    Dict,
    Any,
    List,
)

from nreports_api.shared import JSON
from order_api import OrderService
from nreports.builders import DataBuilder


class DeliveryFeeBuilder(DataBuilder):

    def build_data(
        self,
        data_to_build: Dict[str, JSON],
        **kwargs: Any,
    ) -> Dict[str, JSON]:

        pos_id = int(kwargs["posId"])
        since_datetime = datetime.datetime.strptime(kwargs["sinceDate"], "%Y%m%d")
        until_datetime = datetime.datetime.strptime(kwargs["untilDate"], "%Y%m%d")
        until_datetime = until_datetime.replace(hour=23, minute=59, second=59)

        data_to_build["STORE_ID"] = self.store_config_repository.get_store_id()
        data_to_build["PERIOD"] = "{} - {}".format(
            since_datetime.strftime("%d/%m/%Y"),
            until_datetime.strftime("%d/%m/%Y"),
        )
        self._build_body(
            pos_id=pos_id,
            data_to_build=data_to_build,
            since_datetime=since_datetime.isoformat(),
            until_datetime=until_datetime.isoformat(),
        )

        return data_to_build

    def _build_body(
        self,
        pos_id: int,
        data_to_build: Dict[str, JSON],
        since_datetime: str,
        until_datetime: str,
    ) -> None:

        order_service = OrderService(
            message_bus=self._message_bus,
            pos_id=pos_id,
        )

        orders = order_service.list_orders(
            state="PAID",
            since=since_datetime,
            until=until_datetime,
            include_property="LOGISTIC_PARTNER_ID",
            property_val="0",
        )
        delivery_info = self._get_delivery_info(orders=orders)

        data_to_build["deliveryInfo"] = delivery_info
        data_to_build["TOTAL_DELIVERIES_QTY"] = sum(item["DELIVERIES_QTY"] for item in delivery_info)
        data_to_build["TOTAL_DELIVERY_PAID"] = sum(item["DELIVERY_FEE"] for item in delivery_info)

    @staticmethod
    def _get_delivery_info(
        orders: List[Dict[str, JSON]],
    ):
        delivery_info_by_delivery_man = {}
        for order in orders:
            delivery_man = order["custom_properties"].get("LOGISTIC_DELIVERYMAN_DATA", "$NOT_IDENTIFIED")
            delivery_fee_value = float(order["custom_properties"].get("DELIVERY_FEE_VALUE", 0))
            if delivery_man not in delivery_info_by_delivery_man:
                delivery_info_by_delivery_man[delivery_man] = {
                    "DELIVERIES_QTY": 1,
                    "DELIVERYMAN_NAME": delivery_man,
                    "DELIVERY_FEE": delivery_fee_value,
                }
                continue

            delivery_info_by_delivery_man[delivery_man]["DELIVERIES_QTY"] += 1
            delivery_info_by_delivery_man[delivery_man]["DELIVERY_FEE"] += delivery_fee_value

        return delivery_info_by_delivery_man.values()
