# -*- coding: utf-8 -*-
from datetime import datetime
from typing import List, Dict

import simplejson as json
from application.configurator import Configurator
from application.model import EventData


class TablePictureInteractor(object):

    def __init__(self, configurations):
        # type: (Configurator) -> None
        self.configs = configurations
        self.logger = self.configs.logger

    def build(self, event_data):
        # type: (EventData) -> str

        start_ts = datetime.strptime((event_data.data.get("startTS") + "Z"), "%Y-%m-%d %H:%M:%SZ")
        start_service_date = datetime.strftime(start_ts, "%Y-%m-%dT%H:%M:%SZ")

        finish_ts = event_data.data.get("finishTS")
        finish_ts = finish_ts + 'Z' if finish_ts not in (None, 'None', '') else start_service_date

        linked_tables = event_data.data.get("linkedTables")
        linked_tables = linked_tables.split(",") if linked_tables is not None else []

        payload = {
            "business-dt": event_data.data.get("businessPeriod"),
            "change": float(event_data.data.get("change") or 0),
            "discount-amount": float(event_data.data.get("discountAmount") or 0),
            "due-amount": float(event_data.data.get("dueAmount") or 0),
            "table-id": event_data.data.get("id"),
            "linked-tables": linked_tables,
            "table-seats": int(event_data.data.get("seats") or 1),
            "table-sector": event_data.data.get("sector"),
            "service-id": int(event_data.data.get("serviceId")),
            "service-type": event_data.data.get("type"),
            "service-type-desc": event_data.data.get("typeDescr"),
            "service-seats": int(event_data.data.get("serviceSeats") or 1),
            "slice-source-table-id": event_data.data.get("sliceSourceTableId") or "",
            "slice-source-service-id": self._get_source_service_id(event_data),
            "start-service-dttm": start_service_date,
            "finish-service-dttm": finish_ts,
            "table-status": event_data.data.get("status"),
            "table-status-desc": event_data.data.get("statusDescr"),
            "tax-total": float(event_data.data.get("taxTotal") or 0),
            "tip": float(event_data.data.get("tip") or 0),
            "total-amount": float(event_data.data.get("totalAmount") or 0),
            "total-tender": float(event_data.data.get("totalTender") or 0),
            "user-id": int(event_data.data.get("userId")),
            "service-properties": self._get_custom_properties(event_data),
            "service-orders": self._get_orders(event_data, "ServiceOrders/ServiceOrder"),
            "payment-orders": self._get_orders(event_data, "PaymentOrders/PaymentOrder")
        }

        return json.dumps(payload, use_decimal=True)

    @staticmethod
    def _get_custom_properties(event_data):
        # type: (EventData) -> Dict

        payload_custom_properties = {}
        custom_properties = event_data.data.find("Properties")
        if custom_properties is not None:
            for key, value in custom_properties.items():
                custom_property_key = key.encode("utf-8")
                payload_custom_properties[custom_property_key] = value

        return payload_custom_properties

    def _get_orders(self, event_data, tag):
        # type: (EventData, unicode) -> List

        payload_orders = []
        for order_line in event_data.data.findall("{}".format(tag)):
            order_id = int(order_line.get("orderId") or -1)
            order_state = order_line.get("state")
            created_at = order_line.get("createdAt")
            if created_at is None:
                self.logger.error("Error getting createdAt for order id: {}".format(str(order_id)))
                created_at = datetime.utcfromtimestamp(0).isoformat()

            order_payload = {
                "order-id": order_id,
                "state": order_state,
                "creation-dttm": created_at + "Z"
            }
            payload_orders.append(order_payload)

        return payload_orders

    @staticmethod
    def _get_source_service_id(event_data):
        # type () -> Optional[int]
        if event_data.data.get("sourceServiceId") is not None:
            return int(event_data.data.get("sourceServiceId"))
        return None
