import os
from datetime import datetime

from configs.firebase import SERVER_TIMESTAMP, db
from functions.Orders import (convertImages, convertOrder, convertOrderItem,
                              convertShippingAddress, saveOrder)
from functions.Products import (convertImage, convertProperty, convertVariant,
                                getProductBySku)
from functions.products.CsvProducts import convertVariantMapping
from functions.Response import API_Error
from functions.Suppliers.BlankProducts import getBlankProduct, getBlankVariant


def csvOrders(data:dict):
    currentUser = data.get('currentUser')
    uid, enterpriseId = currentUser.get('uid'), currentUser.get('enterpriseId')
    csvOrders = data.get("csvData")
    mappedValues = data.get("mappedValues")
    placementMapping = data.get("placementMapping")
    orderIds = []
    SKUs = {}
    for order in csvOrders:
        try:
            orderId = str(order[int(mappedValues.get("orderId"))])
            orderIds.append(orderId)
            skuField = mappedValues.get("sku")
            productIdField = mappedValues.get("productId")
            if skuField:SKUs[orderId] = SKUs.get(orderId, []) + [order[int(skuField)]]
            else:SKUs[orderId] = SKUs.get(orderId, []) + [order[int(productIdField)]]
        except:raise API_Error("Missing Order ID or SKU parameter.", 404)
    found_listing_ids = {}
    skuNotFound = []
    for order in csvOrders:
        skuField = mappedValues.get("sku")
        productIdField = mappedValues.get("productId")
        orderSKU = str(order[int(productIdField if productIdField else skuField)])
        printImagesField = mappedValues.get("images")
        # try:
        #     imageUrl = str(order[int(mappedValues.get("printingImage"))])
        #     placement = str(order[int(mappedValues.get("placement"))])
        # except:
        #     imageUrl = None
        #     placement = None
        if not printImagesField and productIdField: raise API_Error("Image placement option is invalid.", 400)
        if orderSKU in ["sku", "SKU"]: raise API_Error("'sku' is not valid SKU, Make sure to check 'Skip First Line' above.", 404)
        if orderSKU not in skuNotFound or orderSKU not in found_listing_ids.keys():
            try:
                # found_listing_ids[orderSKU] = findProduct(uid, orderSKU, NoListing=bool(productIdField))
                found_listing_ids[orderSKU] = findBlankVariantByGtin(enterpriseId, orderSKU)
            except API_Error as e:
                print(e)
                skuNotFound.append(orderSKU)
    if len(skuNotFound)>0: raise API_Error(f"{len(skuNotFound)} SKUs not found.", 404, meta=dict(skuNotFound=skuNotFound))
    doneOrderIds = []
    newOrders = []
    newOrderIds = []
    csvBatchId = str(int(datetime.now().timestamp()))
    for orderId in set(orderIds):
        thisOrderConvertedItems = []
        if orderId not in doneOrderIds:
            thisOrderItems = [o for o in csvOrders if str(o[int(mappedValues.get("orderId"))]) == orderId]
            try:
                firstName = str(thisOrderItems[0][int(mappedValues.get("firstName"))])
                lastName = str(thisOrderItems[0][int(mappedValues.get("lastName"))])
                address1 = str(thisOrderItems[0][int(mappedValues.get("address1"))])
                address2 = str(thisOrderItems[0][int(mappedValues.get("address2"))]) if mappedValues.get("address2") else None
                city = str(thisOrderItems[0][int(mappedValues.get("city"))])
                state = str(thisOrderItems[0][int(mappedValues.get("state"))])
                zip = str(thisOrderItems[0][int(mappedValues.get("zip"))])
                country = "United States"
                # shippingLabel  = str(thisOrderItems[0][int(mappedValues.get("shippingLabel"))])
                # carrierName = str(thisOrderItems[0][int(mappedValues.get("carrierName"))])
                # carrierService = str(thisOrderItems[0][int(mappedValues.get("carrierService"))])
                # trackingCode = str(thisOrderItems[0][int(mappedValues.get("trackingCode"))])
                # quantity  = int(thisOrderItems[0][int(mappedValues.get("quantity"))])
                # print(quantity)
            except Exception as e: raise API_Error(f"Missing Order Details: {e}", 400)
            shippingLabel  = None
            carrierName = None
            carrierService = None
            trackingCode = None
            try:
                shippingLabel  = str(thisOrderItems[0][int(mappedValues.get("shippingLabel"))])
                carrierName = str(thisOrderItems[0][int(mappedValues.get("carrierName"))])
                carrierService = str(thisOrderItems[0][int(mappedValues.get("carrierService"))])
                trackingCode = str(thisOrderItems[0][int(mappedValues.get("trackingCode"))])
            except: pass
            itemsCount = 0
            for item in thisOrderItems:
                printImageFields = mappedValues.get("images")
                printImages = []
                mockImageFields =mappedValues.get("productImages")
                productImage = None
                for field in mockImageFields:
                    productImage = dict(url=item[int(field)])
                if printImageFields:
                    for field in printImageFields:
                        imageUrl = str(item[int(field.get("image"))])
                        placement = placementMapping.get(str(item[int(field.get("placement"))]))
                        if (imageUrl and placement):
                            imageName = os.path.basename(imageUrl)
                            printImages.append(convertImages(
                                uid=uid,
                                enterpriseId=enterpriseId,
                                url=imageUrl,
                                placement=placement,
                                name=imageName
                            ))
                skuField =  mappedValues.get("sku")
                productIdField = mappedValues.get("productId")
                sku = str(item[int(productIdField if productIdField else skuField)])
                product,  productMapping,variant, variantMapping = found_listing_ids[sku]
                price =  variant.get('price', 0 ) if variant.get('price', 0 ) else 0
                # print(orderId, sku, printImages)
                poData = dict(variantMapping)
                if printImages: poData['images'] = printImages
                quantity  = int(item[int(mappedValues.get("quantity"))])
                thisItemTotal= price * quantity
                thisOrderItem = convertOrderItem(
                    uid=uid,
                    enterpriseId=enterpriseId,
                    platformOrderId=orderId,
                    platformProductId=product.get('id'),
                    createdAt=SERVER_TIMESTAMP,
                    updatedAt=SERVER_TIMESTAMP,
                    platformId="0",
                    variant=variant,
                    quantity=quantity,
                    price=thisItemTotal,
                    variantId=variant.get('id'),
                    shopId=uid+'0',
                    product=product,
                    productMapping=productMapping,
                    variantMapping=poData,
                    platformOrderItemId=str(orderId+str(itemsCount)),
                    # printingImages=list(printImages),
                    image=productImage
                )
                thisOrderConvertedItems.append(thisOrderItem)
                itemsCount+=1
            thisOrder = convertOrder(
                uid=uid,
                platformId="0",
                shopId="0"+uid,
                enterpriseId=enterpriseId,
                shippingAddress=convertShippingAddress(
                    name= f"{firstName} {lastName}",
                    address1=address1,
                    address2=address2,
                    city=city,
                    state=state,
                    zip=zip,
                    country=country,
                ),
                createdAt=SERVER_TIMESTAMP,
                updatedAt=SERVER_TIMESTAMP,
                grandTotal=sum([i.get('price',0) for i in thisOrderConvertedItems]),
                platformOrderId=orderId,
                metadata = dict(
                            tags=["CSV",csvBatchId],
                            shippingLabel  = shippingLabel,
                            carrierName = carrierName,
                            carrierService = carrierService,
                            trackingCode =trackingCode
                        )
            )
            doneOrderIds.append(orderId)
            # print(thisOrder, thisOrderConvertedItems)
            newOrders.append((thisOrder, thisOrderConvertedItems))
    c = 1
    for order, items in newOrders:
        id = saveOrder(order, items)
        print("SAVED ORDER", c, order.get("platformOrderId"))
        newOrderIds.append(dict(
            id=id,
            platformOrderId=order.get("platformOrderId")
        ))
    return newOrderIds

def findProduct(uid ,sku, NoListing=False):
    if NoListing:
        blankProductId, blankVariantId = sku.split("-")
        blankProduct = getBlankProduct(blankProductId)
        blankVariant = getBlankVariant(blankProductId, blankVariantId)
        return blankProduct, {}, convertVariant(id=sku,sku=sku, properties=[
            convertProperty(
                name='Color',
                value=blankVariant.get('color'),
            ),
            convertProperty(
                name='Size',
                value=blankVariant.get('size'),
            ),
        ]), convertVariantMapping(blankProductId=blankProductId, blankVariantId=blankVariantId, gtin=blankVariant.get('gtin'), id=sku, sku=sku)
    else:
        product, variant, variantMapping = getProductBySku(uid, sku)
        return product, product.get("productMapping"), variant, variantMapping
    

def findBlankVariantByGtin(enterpriseId, gtin, supplierId="SS"):
    ref = db.document(f"gtins/{gtin}").get()
    if ref.exists:
        data = ref.to_dict()
        suppliers = data.get("suppliers")
        gtinProduct = suppliers.get(supplierId)
        if not gtinProduct: 
            relatedBlankProducts = data.get("relatedBlankProducts", [])
            for blankProductId in relatedBlankProducts:
                blankSettingsRef = db.document(f"enterprises/{enterpriseId}/blankProducts/{blankProductId}").get()
                if blankSettingsRef.exists: 
                   for k, v in suppliers.items():
                          if v.get("blankProductId") == blankProductId:
                            gtinProduct = v
                            break
                if gtinProduct: break
            # else: gtinProduct = suppliers.get(list(suppliers.keys())[0])
        if not gtinProduct: raise API_Error(f"GTIN not found. {gtin}", 404)
        blankProductId, blankVariantId = gtinProduct.get("blankProductId"), gtinProduct.get("blankVariantId")
        blankProduct = db.document(f"blankProducts/{blankProductId}").get().to_dict()
        blankVariant = db.document(f"blankProducts/{blankProductId}/blankVariants/{blankVariantId}").get().to_dict()
        return blankProduct, {}, convertVariant(id=gtin,sku=gtin, properties=[
            convertProperty(
                name='Color',
                value=blankVariant.get('color'),
            ),
            convertProperty(
                name='Size',
                value=blankVariant.get('size'),
            ),
        ]), convertVariantMapping(blankProductId=blankProductId, blankVariantId=blankVariantId, gtin=gtin, id=gtin, sku=gtin, images=[])
    print("Not found", gtin)
    return None

