import json
import unittest
import time
from datetime import datetime, timedelta
from threading import Thread

import zmq
from messagebus import Event, Message, TokenCreator, TokenPriority, DataType, DefaultToken
from zeromqmessagehandler import ZeroMqMessageBus

SERVICE_LOCATOR_GROUP = "3"
TK_SERVICE_LOCATOR_LOOKUP_SERVICE = TokenCreator.create_token(TokenPriority.high, SERVICE_LOCATOR_GROUP, "2")


class PublishTestCase(unittest.TestCase):
    def test_publish(self):
        ctx = zmq.Context()

        pub_socket = ctx.socket(zmq.PUB)
        pub_socket.connect("tcp://localhost:5000")

        data1 = {

        }
        data2 = {
            "id": "asdf",
            "code": "asdf",
            "partner": "Teste",
            "storeCode": "99994"
        }
        data3 = {
            "orderCode": "12",
            "partnerId": "8",
            "fromStatus": "",
            "toStatus": ""
        }
        data4 = {
        }
        data5 = {
            "id": "asdf"
        }
        event1 = Event("StoreStatusUpdate", data=json.dumps(data1).encode("utf-8"))
        event2 = Event("OrderManagerOrderIntegrated", data=json.dumps(data2).encode("utf-8"))
        event3 = Event("OrderStatusCodeUpdated", data=json.dumps(data3).encode("utf-8"))
        event4 = Event("PublishMenuVersion", data=json.dumps(data4).encode("utf-8"), headers={"context": "localhost"})
        event5 = Event("PosOrderConfirm", data=json.dumps(data5).encode("utf-8"))
        method = "POST"
        path = "/mwboh-api/v1.0.0/sale/order-picture"
        headers = {
            "x-api-key": "58b333b4-449b-4f08-b81a-bd48b658e266"
        }
        data = f"{method}\0{path}\0{len(headers)}\0"
        if len(headers) > 0:
            for header in headers.keys():
                data += header + "\0" + headers[header]
            data += "\0"
        query_params = {}
        data += str(len(query_params)) + "\0"
        if len(query_params) > 0:
            for query_param in query_params.keys():
                data += query_param + "\0" + query_params[query_param]
            data += "\0"
        body = """{"order-code":"9","order-picture-sale-lines":[{"comment":[],"unit-price":4.9,"menu-item-code":"1","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[{"base-amount-bd":4.9,"base-amount-ad":2.29,"tax-index":"PIS;P","tax-amount-bd":0.196,"tax-rule-id":1955574606,"tax-rate":0.04,"tax-amount-ad":0.0916},{"base-amount-bd":4.9,"base-amount-ad":2.29,"tax-index":"COFINS;C","tax-amount-bd":0.245,"tax-rule-id":2143042763,"tax-rate":0.05,"tax-amount-ad":0.1145},{"base-amount-bd":4.9,"base-amount-ad":2.29,"tax-index":"ICMS;I","tax-amount-bd":0.637,"tax-rule-id":1707847563,"tax-rate":0.13,"tax-amount-ad":0.2977}],"default-qty":null,"item-type":"PRODUCT","sub-qty":null,"discount-applied":"600:2.61","added-qty":null,"product":"X-Burger","item-discount":2.61,"dec-qty":0,"multiplied-qty":1,"chosen-qty":null,"price-key":"249108103194","added-unit-price":0.0,"level":0,"item-price":4.9,"order-picture-id":6,"custom-properties":{"a":"b"},"part-code":"1001","plu":"1001","line-number":1},{"comment":[],"unit-price":0.0,"menu-item-code":"1.1001","qty":0,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[],"default-qty":0,"item-type":"OPTION","sub-qty":0,"discount-applied":null,"added-qty":0,"product":"Ponto da Carne","item-discount":0.0,"dec-qty":0,"multiplied-qty":0.0,"chosen-qty":0,"price-key":null,"added-unit-price":0.0,"level":1,"item-price":0.0,"order-picture-id":6,"custom-properties":{},"part-code":"700000001","plu":"700000001","line-number":1},{"comment":[],"unit-price":0.0,"menu-item-code":"1.1001","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[],"default-qty":1,"item-type":"OPTION","sub-qty":0,"discount-applied":null,"added-qty":0,"product":"Maionese Extra","item-discount":0.0,"dec-qty":0,"multiplied-qty":1.0,"chosen-qty":1,"price-key":null,"added-unit-price":0.0,"level":1,"item-price":0.0,"order-picture-id":6,"custom-properties":{},"part-code":"900000002","plu":"900000002","line-number":1},{"comment":[],"unit-price":0.0,"menu-item-code":"1.1001.900000002","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[{"base-amount-bd":2.0,"base-amount-ad":0.94,"tax-index":"PIS;P","tax-amount-bd":0.07,"tax-rule-id":27939140,"tax-rate":0.035,"tax-amount-ad":0.0329},{"base-amount-bd":2.0,"base-amount-ad":0.94,"tax-index":"COFINS;C","tax-amount-bd":0.07,"tax-rule-id":190559478,"tax-rate":0.035,"tax-amount-ad":0.0329},{"base-amount-bd":2.0,"base-amount-ad":0.94,"tax-index":"ICMS;I","tax-amount-bd":0.24,"tax-rule-id":1678362044,"tax-rate":0.12,"tax-amount-ad":0.1128}],"default-qty":null,"item-type":"CANADD","sub-qty":null,"discount-applied":"600:1.06","added-qty":null,"product":"Maionese","item-discount":1.06,"dec-qty":0,"multiplied-qty":1.0,"chosen-qty":null,"price-key":"249108103236","added-unit-price":2.0,"level":2,"item-price":2.0,"order-picture-id":6,"custom-properties":{},"part-code":"10101","plu":"10101","line-number":1},{"comment":[],"unit-price":0.0,"menu-item-code":"1","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[],"default-qty":null,"item-type":"COMBO","sub-qty":null,"discount-applied":null,"added-qty":null,"product":"Combo X-Burger","item-discount":0.0,"dec-qty":0,"multiplied-qty":1,"chosen-qty":null,"price-key":null,"added-unit-price":0.0,"level":0,"item-price":0.0,"order-picture-id":6,"custom-properties":{},"part-code":"20001","plu":"20001","line-number":2},{"comment":[],"unit-price":4.9,"menu-item-code":"1.20001","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[{"base-amount-bd":4.9,"base-amount-ad":2.29,"tax-index":"PIS;P","tax-amount-bd":0.196,"tax-rule-id":1955574606,"tax-rate":0.04,"tax-amount-ad":0.0916},{"base-amount-bd":4.9,"base-amount-ad":2.29,"tax-index":"COFINS;C","tax-amount-bd":0.245,"tax-rule-id":2143042763,"tax-rate":0.05,"tax-amount-ad":0.1145},{"base-amount-bd":4.9,"base-amount-ad":2.29,"tax-index":"ICMS;I","tax-amount-bd":0.637,"tax-rule-id":1707847563,"tax-rate":0.13,"tax-amount-ad":0.2977}],"default-qty":1,"item-type":"PRODUCT","sub-qty":0,"discount-applied":"600:2.61","added-qty":0,"product":"X-Burger","item-discount":2.61,"dec-qty":0,"multiplied-qty":1.0,"chosen-qty":null,"price-key":"249108103219","added-unit-price":0.0,"level":1,"item-price":4.9,"order-picture-id":6,"custom-properties":{},"part-code":"1001","plu":"1001","line-number":2},{"comment":[],"unit-price":0.0,"menu-item-code":"1.20001.1001","qty":0,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[],"default-qty":0,"item-type":"OPTION","sub-qty":0,"discount-applied":null,"added-qty":0,"product":"Ponto da Carne","item-discount":0.0,"dec-qty":0,"multiplied-qty":0.0,"chosen-qty":0,"price-key":null,"added-unit-price":0.0,"level":2,"item-price":0.0,"order-picture-id":6,"custom-properties":{},"part-code":"700000001","plu":"700000001","line-number":2},{"comment":[],"unit-price":0.0,"menu-item-code":"1.20001.1001","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[],"default-qty":1,"item-type":"OPTION","sub-qty":0,"discount-applied":null,"added-qty":0,"product":"Maionese Extra","item-discount":0.0,"dec-qty":0,"multiplied-qty":1.0,"chosen-qty":1,"price-key":null,"added-unit-price":0.0,"level":2,"item-price":0.0,"order-picture-id":6,"custom-properties":{},"part-code":"900000002","plu":"900000002","line-number":2},{"comment":[],"unit-price":0.0,"menu-item-code":"1.20001.1001.900000002","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[{"base-amount-bd":2.0,"base-amount-ad":0.94,"tax-index":"PIS;P","tax-amount-bd":0.07,"tax-rule-id":27939140,"tax-rate":0.035,"tax-amount-ad":0.0329},{"base-amount-bd":2.0,"base-amount-ad":0.94,"tax-index":"COFINS;C","tax-amount-bd":0.07,"tax-rule-id":190559478,"tax-rate":0.035,"tax-amount-ad":0.0329},{"base-amount-bd":2.0,"base-amount-ad":0.94,"tax-index":"ICMS;I","tax-amount-bd":0.24,"tax-rule-id":1678362044,"tax-rate":0.12,"tax-amount-ad":0.1128}],"default-qty":null,"item-type":"CANADD","sub-qty":null,"discount-applied":"600:1.06","added-qty":null,"product":"Maionese","item-discount":1.06,"dec-qty":0,"multiplied-qty":1.0,"chosen-qty":null,"price-key":"249108103236","added-unit-price":2.0,"level":3,"item-price":2.0,"order-picture-id":6,"custom-properties":{},"part-code":"10101","plu":"10101","line-number":2},{"comment":[],"unit-price":0.0,"menu-item-code":"1.20001","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[],"default-qty":1,"item-type":"OPTION","sub-qty":0,"discount-applied":null,"added-qty":0,"product":"Bebida","item-discount":0.0,"dec-qty":0,"multiplied-qty":1.0,"chosen-qty":1,"price-key":null,"added-unit-price":0.0,"level":1,"item-price":0.0,"order-picture-id":6,"custom-properties":{},"part-code":"900000003","plu":"900000003","line-number":2},{"comment":[],"unit-price":2.5,"menu-item-code":"1.20001.900000003","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[{"base-amount-bd":2.5,"base-amount-ad":1.17,"tax-index":"PIS;P","tax-amount-bd":0.1,"tax-rule-id":1955574606,"tax-rate":0.04,"tax-amount-ad":0.0468},{"base-amount-bd":2.5,"base-amount-ad":1.17,"tax-index":"COFINS;C","tax-amount-bd":0.125,"tax-rule-id":2143042763,"tax-rate":0.05,"tax-amount-ad":0.0585},{"base-amount-bd":2.5,"base-amount-ad":1.17,"tax-index":"ICMS;I","tax-amount-bd":0.0,"tax-rule-id":1707847563,"tax-rate":0.13,"tax-amount-ad":0.0}],"default-qty":null,"item-type":"CANADD","sub-qty":null,"discount-applied":"600:1.33","added-qty":null,"product":"Coca Cola","item-discount":1.33,"dec-qty":0,"multiplied-qty":1.0,"chosen-qty":null,"price-key":"249108103238","added-unit-price":0.0,"level":2,"item-price":2.5,"order-picture-id":6,"custom-properties":{},"part-code":"2001","plu":"2001","line-number":2},{"comment":[],"unit-price":0.0,"menu-item-code":"1.20001","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[],"default-qty":1,"item-type":"OPTION","sub-qty":0,"discount-applied":null,"added-qty":0,"product":"Batata","item-discount":0.0,"dec-qty":0,"multiplied-qty":1.0,"chosen-qty":1,"price-key":null,"added-unit-price":0.0,"level":1,"item-price":0.0,"order-picture-id":6,"custom-properties":{},"part-code":"900000004","plu":"900000004","line-number":2},{"comment":[],"unit-price":2.5,"menu-item-code":"1.20001.900000004","qty":1,"inc-qty":0,"sub-unit-price":0.0,"tax-items":[{"base-amount-bd":2.5,"base-amount-ad":1.17,"tax-index":"PIS;P","tax-amount-bd":0.1,"tax-rule-id":1955574606,"tax-rate":0.04,"tax-amount-ad":0.0468},{"base-amount-bd":2.5,"base-amount-ad":1.17,"tax-index":"COFINS;C","tax-amount-bd":0.1,"tax-rule-id":2122209020,"tax-rate":0.04,"tax-amount-ad":0.0468},{"base-amount-bd":2.5,"base-amount-ad":1.17,"tax-index":"ICMS;I","tax-amount-bd":0.425,"tax-rule-id":1656883031,"tax-rate":0.17,"tax-amount-ad":0.1989}],"default-qty":null,"item-type":"CANADD","sub-qty":null,"discount-applied":"600:1.33","added-qty":null,"product":"Batata Média","item-discount":1.33,"dec-qty":0,"multiplied-qty":1.0,"chosen-qty":null,"price-key":"249108103246","added-unit-price":0.0,"level":2,"item-price":2.5,"order-picture-id":6,"custom-properties":{},"part-code":"3002","plu":"3002","line-number":2}],"total-gross":8.8,"store-code":"test-menu2","tax-applied":1.76,"xml-data":" ","total-after-discount":7.04,"session":"pos=1,user=1,count=1,period=20210707","sale-type-id":0,"tax-total":1.76,"due-amount":0.0,"change":0.0,"originator-code":"1","pos-code":"1","price-list":"EI","exemption":null,"discount-amount":10.0,"type-id":0,"price-basis":"G","tip":0.0,"business-dt":"2021-07-07","order-picture-tenders":[{"tender-type":"0","reference-amount":8.8,"tender-detail":null,"tip":null,"tender-amount":8.8,"order-picture-id":6,"change-amount":0.0}],"total-amount":17.04,"creation-dttm":"2021-07-07T17:13:39.855Z","total-tender":8.8,"pos-user-id":"1","total-gift":0,"discount-applied":null,"state-id":5,"order-discount-amount":0.0,"pod-type":"FL","order-picture-custom-order-properties":{"DISCOUNT_APPLY_OPERATOR":"1","BENEFIT_LIST":"[{\\"promotion_tender_amount\\": 0, \\"added_sale_lines\\": [], \\"benefit\\": \\"{\\\\\\"priority\\\\\\": 1, \\\\\\"userDescription\\\\\\": \\\\\\"Desconto por valor\\\\\\", \\\\\\"id\\\\\\": \\\\\\"1\\\\\\", \\\\\\"actions\\\\\\": {\\\\\\"1\\\\\\": {\\\\\\"discountAmountOnTotal\\\\\\": 10}}, \\\\\\"name\\\\\\": \\\\\\"Valor\\\\\\"}\\", \\"burnt_items\\": {}, \\"used_discount_ids\\": [600], \\"tender_id\\": \\"60\\"}]","FISCALIZATION_DATE":"2021-07-07T17:14:21","DISCOUNT_APPLY_AUTHORIZER":"1","DISCOUNT_APPLY_METHOD":"VLR11","DISCOUNT_APPLY_DATETIME":"2021-07-07T14:13:47"}}"""
        data += body
        data = data.encode("utf-8")

        event6 = Event("WsgiRequest", data=data, headers={"context": "localhost"})
        event7 = Event("ConsolidateSales", data=b"", headers={"context": "dev.backoffice.hmledp.com.br"})
        event8 = Event("FetchTefReconciliationReportData", data=b"", headers={"context": "127.0.0.1"})
        time.sleep(0.5)
        count = 1
        now = datetime.now()
        stop = now + timedelta(seconds=60)
        while datetime.now() < stop and count <= 1:
            pub_socket.send(format_event(event6))
            # pub_socket.send(format_event(event8))
            # pub_socket.send(format_event(event3))
            count += 1

        pub_socket.close()

        ctx.destroy()
        print(count)

    def test_message(self):
        context = zmq.Context()
        message_bus = ZeroMqMessageBus("EventManager", context)

        threads = []
        threads.extend(create_threads(1, send_slow_event, [message_bus, 1]))
        threads.extend(create_threads(30, send_fast_event, [message_bus, 5]))

        for t in threads:
            t.join()

        print("OK")


def create_threads(qty, target, args):
    threads = []
    for i in range(0, qty):
        t = Thread(target=target, args=args)
        t.start()
        threads.append(t)

    return threads


def send_slow_event(message_bus, qty):
    for i in range(0, qty):
        try:
            print(i)
            message_bus.publish_event(
                Event(
                    "WsgiRequest",
                    data=b"GET\0/test\0000\0000\0",
                    synchronous=True,
                    headers={"context": "localhost"}))
        except Exception as ex:
            print("Error on event: {}".format(ex))

    print("Sent {} events".format(qty))


def send_fast_event(message_bus, qty):
    for i in range(0, qty):
        reply = message_bus.publish_event(
            Event(
                "WsgiRequest",
                data=b"GET\0/test2\0000\0000\0",
                synchronous=True,
                headers={"context": "localhost"}))
        if reply.token != DefaultToken.TK_SYS_ACK:
            raise Exception("Error")
    print("Sent {} events".format(qty))


def convert_dict_to_bytes(d):
    if d is not None:
        ret = str(len(d)).encode("utf-8") + b"\0"
        for key in d.keys():
            ret += key.encode("utf-8") + b"\0" + d[key].encode("utf-8") + b"\0"
        ret = ret[:-1]
        return ret
    return b""


def format_event(event):
    # type: (Event) -> bytes
    type_data = event.event_type.encode("utf-8") if event.event_type is not None else b""
    event_data = b"" if event.data is None else event.data
    return event.subject.encode("utf-8") + b" " + type_data + b"\0" + convert_dict_to_bytes(event.headers) + b"\0" + event_data
