import traceback
from datetime import datetime

import pytz
import requests

from configs.firebase import SERVER_TIMESTAMP, ArrayUnion, db
from functions.LastUpdated import ordersLastUpdated, saveOrdersLastUpdated
from functions.Orders import (convertOrder, convertOrderItem,
                              convertShippingAddress, saveOrder)
from functions.Products import (convertProduct, convertProperty,
                                convertVariant, saveProduct)
from functions.Response import API_Error, saveError
from functions.Shipments.Convert import saveShipment
from functions.Shipstation.Auth import Authorization
from functions.Shops import getShopById, getShops
from V2.functions.Shops.main import Shop, disableShop
from V2.Params import Params


def updateAllOrders(params={}):
    shops = getShops(platformId="5", credentials= True)
    res = [updateShopOrders(shop) for shop in shops if not shop.get("disabled")]
    return str(res)

def updateShopOrders(shop:dict):
    try:
        if shop:
            uid = shop.get('uid')
            shopId  = shop.get('id')
            # if shopId not in  ["vAJBtdQOKYT7m6xVNL6i", "d8eIUis1u8EwOCnBjG6t"]:return
            apiKey = shop.get('apiKey')
            apiSecret = shop.get('apiSecret')
            enterpriseId = shop.get('enterpriseId')
            platformShopIds = shop.get("platformShopIds")
            authorization = Authorization(apiKey, apiSecret)
            lastUpdate = ordersLastUpdated(shopId)
            delay = 86400
            if uid in ["S6cjn7gKnDh2O6OGNaZRrZPdYlh2","gG895WoY1TWSCwGgNCGupORs7Xg1"]: delay = 3600
            updated_at_min= datetime.fromtimestamp(lastUpdate.get("timestamp") - delay, pytz.utc).isoformat()
            nowTimestamp = int(datetime.now(pytz.utc).timestamp())
            orders = getOrders(authorization, updated_at_min, platformShopIds, shopId)
            updates = []
            for order in orders:
                orderId = order.get('orderId')
                orderNumber = order.get('orderNumber')
                tagIds = order.get("tagIds", [])
                thisShopId = order.get("shopId")
                thisStoreId = str(order.get("storeId"))
                if not tagIds: tagIds = []
                if uid in ["S6cjn7gKnDh2O6OGNaZRrZPdYlh2","gG895WoY1TWSCwGgNCGupORs7Xg1"] and 125364 not in tagIds:continue
                shippingAddress = order.get('shipTo')
                shipped = order.get("orderStatus") == "shipped"
                cancelled = order.get("orderStatus") == "cancelled"
                shippingAddress = convertShippingAddress(
                        name=shippingAddress.get('name'),
                        address1=shippingAddress.get('street1'),
                        address2=shippingAddress.get('street2'),
                        city=shippingAddress.get('city'),
                        state=shippingAddress.get('state'),
                        zip=shippingAddress.get('postalCode'),
                        country=shippingAddress.get('country'),
                        phone=shippingAddress.get('phone'),
                    )
                etsyConnections = shop.get("etsyConnections", [])
                thisEtsyConnection = next((conn for conn in etsyConnections if str(conn.get("shipstationPlatformShopId")) == thisStoreId), None)
                if thisEtsyConnection: continue
                convertedOrder = convertOrder(
                    uid=uid,
                    platformId = shop.get("platformId"),
                    shopId = shopId,
                    enterpriseId=enterpriseId,
                    shippingAddress=shippingAddress,
                    createdAt = SERVER_TIMESTAMP,
                    updatedAt = SERVER_TIMESTAMP,
                    grandTotal = order.get('orderTotal'),
                    platformOrderId=orderId,
                    orderNumber=orderNumber,
                    shipped=shipped,
                    cancelled=cancelled,
                    shopName=next((shop.get("name") for shop in shop.get("platformShops") if shop.get("id") == thisShopId), "Unknown"),
                )
                items = order.get('items', [])
                convertedOrderitems = []
                blocked_props = [
                    "_inkybay_same_design_items",
                    "_inkybay_option_id",
                    "_inkybay_option_data",
                    "_inkybay_customization_id"
                ]
                for item in items:
                    platformOrderItemId = str(item.get('orderItemId'))
                    sku = item.get('sku')
                    variantId = sku if sku else platformOrderItemId
                    variant = convertVariant(
                            id=variantId,
                            sku=sku,
                            deleted=False,
                            properties=[convertProperty(
                                name=p.get('name'),
                                value=p.get('value'),
                            ) for p in item.get('options', []) if p.get('name') not in blocked_props],
                        )
                    if shop.get('enterpriseId') == "lJ2eUFov5WyPlRm4geCr": 
                        variant['sku'] = None
                        variant['id'] = platformOrderItemId
                        variantId = platformOrderItemId
                    convertedProduct = convertProduct(
                        uid=uid,
                        enterpriseId=enterpriseId,
                        platformProductId=item.get('productId'),
                        platformId="5",
                        shopId=shopId,
                        name=item.get('name'),
                        description="",
                        createdAt=SERVER_TIMESTAMP,
                        updatedAt=SERVER_TIMESTAMP,
                        price=item.get('unitPrice'),
                        tags=[],
                        images=[dict(url = item.get('imageUrl'))],
                    )
                    # variant['properties'] = variant.get("properties")[:2]
                    productId = saveProduct(convertedProduct, [variant])
                    convertedOrderItem = convertOrderItem(
                        uid=uid,
                        enterpriseId=enterpriseId,
                        platformId=shop.get("platformId"),
                        platformProductId=item.get('productId'),
                        platformOrderItemId=platformOrderItemId,
                        platformOrderId=orderId,
                        quantity=item.get('quantity'),
                        price=item.get('unitPrice'),
                        variantId=sku,
                        createdAt=SERVER_TIMESTAMP,
                        updatedAt=SERVER_TIMESTAMP,
                        shopId=shopId,
                        image=dict(url = item.get('imageUrl')),
                        name= item.get('name'),
                        variant = variant,
                        shipped=shipped,
                        cancelled=cancelled,
                        product={"id": productId, **convertedProduct}
                    )
                    convertedOrderitems.append(convertedOrderItem)
                id = saveOrder(convertedOrder, convertedOrderitems)
                # if shipped:
                #     # shipments = getShipment(authorization, orderId, uid, shopId)
                #     if shipments:
                #         for shipment in shipments:
                #             trackingNumber = shipment.get('trackingNumber')
                #             carrierCode = shipment.get('carrierCode')
                #             saveShipment(
                #                 uid, enterpriseId, platformId = "5", 
                #                 platformName="SHIPSTATION",
                #                 orderId = id,
                #                 platformOrderId=orderId,
                #                 image=None,
                #                 carrierName=carrierCode,
                #                 carrierService=carrierCode,
                #                 cost=shipment.get('shipmentCost'),
                #                 currency="USD",
                #                 pdf=None,
                #                 platformShipmentId=shipment.get('shipmentId'),
                #                 trackingCode=trackingNumber,
                #                 userUid=uid,
                #                 labelData=shipment.get('labelData'),
                #             )
                updates.append(dict(id=id, orderId=orderId))
            saveOrdersLastUpdated(shopId = shopId, count= len(updates), timestamp=nowTimestamp - 1800)
            return f"Orders updated => {len(updates)}"
    except Exception as e:
        traceback.print_exc()
        saveError(uid, "Shipstation/Orders/updateShopOrders", str(e),data =  dict(
            shopId=shopId,
            lastUpdate=lastUpdate
        ))
    return "No Updates"

def updateSingleOrder(shop:Shop, platformOrderId:str, readd=False):
    shopId = shop.id
    uid = shop.uid
    apiKey = shop.apiKey
    apiSecret = shop.apiSecret
    enterpriseId = shop.enterpriseId
    authorization = Authorization(apiKey, apiSecret)
    order = getOrder(authorization, platformOrderId)
    orderNumber = order.get('orderNumber')
    shippingAddress = order.get('shipTo')
    shipped = order.get("orderStatus") == "shipped"
    cancelled = order.get("orderStatus") == "cancelled"
    convertedOrder = convertOrder(
        uid=uid,
        platformId = shop.platformId,
        shopId = shopId,
        enterpriseId=enterpriseId,
        shippingAddress=convertShippingAddress(
            name=shippingAddress.get('name'),
            address1=shippingAddress.get('street1'),
            address2=shippingAddress.get('street2'),
            city=shippingAddress.get('city'),
            state=shippingAddress.get('state'),
            zip=shippingAddress.get('postalCode'),
            country=shippingAddress.get('country'),
            phone=shippingAddress.get('phone'),
        ),
        createdAt = SERVER_TIMESTAMP,
        updatedAt = SERVER_TIMESTAMP,
        grandTotal = order.get('orderTotal'),
        platformOrderId=platformOrderId,
        orderNumber=orderNumber,
        shipped=shipped,
        cancelled=cancelled,
        shopName=shop.name,
    )
    items = order.get('items', [])
    convertedOrderitems = []
    blocked_props = [
        "_inkybay_same_design_items",
        "_inkybay_option_id",
        "_inkybay_option_data",
        "_inkybay_customization_id"
    ]
    for item in items:
        platformOrderItemId = str(item.get('orderItemId'))
        sku = item.get('sku')
        variantId = sku if sku else platformOrderItemId
        variant = convertVariant(
                id=variantId,
                sku=sku,
                deleted=False,
                properties=[convertProperty(
                    name=p.get('name'),
                    value=p.get('value'),
                ) for p in item.get('options', []) if p.get('name') not in blocked_props],
            )
        if shop.enterpriseId == "lJ2eUFov5WyPlRm4geCr": 
            variant['sku'] = None
            variant['id'] = platformOrderItemId
            variantId = platformOrderItemId
        productId = item.get('productId') if item.get("productId") not in [None, "None"] else platformOrderItemId
        convertedProduct = convertProduct(
            uid=uid,
            enterpriseId=enterpriseId,
            platformProductId=productId,
            platformId="5",
            shopId=shopId,
            name=item.get('name'),
            description="",
            createdAt=SERVER_TIMESTAMP,
            updatedAt=SERVER_TIMESTAMP,
            price=item.get('unitPrice'),
            tags=[],
            images=[dict(url = item.get('imageUrl'))],
        )
        
        # variant['properties'] = variant.get("properties")[:2]
        productId = saveProduct(convertedProduct, [variant])
        convertedOrderItem = convertOrderItem(
            uid=uid,
            enterpriseId=enterpriseId,
            platformId=shop.platformId,
            platformProductId=productId,
            platformOrderItemId=platformOrderItemId,
            platformOrderId=platformOrderId,
            quantity=item.get('quantity'),
            price=item.get('unitPrice'),
            variantId=variantId,
            createdAt=SERVER_TIMESTAMP,
            updatedAt=SERVER_TIMESTAMP,
            shopId=shopId,
            image=dict(url = item.get('imageUrl')),
            name= item.get('name'),
            variant = variant,
            shipped=shipped,
            cancelled=cancelled,
            product=convertedProduct
        )
        convertedOrderitems.append(convertedOrderItem)
    id = saveOrder(convertedOrder, convertedOrderitems,rewrites=True, readd=readd)
    return id

def getOrder(Authorization, orderId):
    url = f"https://ssapi.shipstation.com/orders/{orderId}"
    res = requests.get(url, auth=Authorization)
    if res.status_code == 200: return res.json()
    print(res.status_code,res.text, orderId)
    return None
    
def findOrder(shop:Shop, **kwargs):
    url = f"https://ssapi.shipstation.com/orders"
    apiKey = shop.apiKey
    apiSecret = shop.apiSecret
    authorization = Authorization(apiKey, apiSecret)
    res = requests.get(url, auth=authorization, params=dict(
                **kwargs
            )
        ) 
    if res.status_code == 200: 
        orders =  res.json().get("orders", [])
        if orders: return orders[0]
    return None

def getOrders(Authorization, updated_at_min=None,platformShopIds=[], shopId = None):
    url = f"https://ssapi.shipstation.com/orders"
    orders = []
    for storeId in platformShopIds:
        res = requests.get(url, auth=Authorization, params=dict(
            sortBy="ModifyDate",
            sortDir="ASC",
            storeId=storeId,
            modifyDateStart = updated_at_min,
            # modifyDateEnd = datetime.fromtimestamp(datetime.now().timestamp() - 1800, pytz.utc).isoformat(),
            pageSize=200
            )
        ) 
        if res.status_code == 200:  orders.extend([{**order, "shopId":shopId, "storeId": storeId} for order in res.json().get('orders', [])])
        if res.text == "401 Unauthorized" and shopId: disableShop(shopId)
    return orders

def getShipment(Authorization, orderId, uid=None, shopId=None):
    url = f"https://ssapi.shipstation.com/shipments"
    res = requests.get(url, auth=Authorization, params=dict(orderId=orderId))
    if res.status_code == 200:
        return res.json().get("shipments", [])
    saveError(uid, "Shipstation/Orders/getShipment", res.text,data=dict(
        shopId=shopId,
        orderId=orderId
    ))
    return []


def submitShipment(shop:Shop, platformOrderId, carrierName, trackingCode):
    today = datetime.today().strftime("%Y-%m-%d")
    data = {
        "orderId": platformOrderId,
        "carrierCode": carrierName,
        "shipDate": today,
        "trackingNumber": trackingCode,
        "notifyCustomer": True,
        "notifySalesChannel": True
    }
    url = f"https://ssapi.shipstation.com/orders/markasshipped"
    authorization = Authorization(shop.apiKey, shop.apiSecret)
    res = requests.post(url, auth=authorization, json=data, headers={"Content-Type": "application/json"})
    return res.status_code == 200