import traceback
from configs.firebase import SERVER_TIMESTAMP, ArrayUnion
from functions.Products import convertProduct, convertProperty, convertVariant
from functions.Response import API_Error
from datetime import datetime
from functions.Suppliers.BlankProducts import getBlankProduct, getBlankVariant
from functions.products.ManualProduct import saveManualProduct

def csvProducts(params:dict):
    csvData = params.get('csvData')
    if len(csvData) > 500:
        raise API_Error("Maximum 500 rows are allowed.", 500, dict(rows=len(csvData)))
    mappedValues = params.get('mappedValues')
    mappedDataOfCsv = params.get('mappedDataOfCsv')
    placementMapping = params.get('placementMapping')
    currentUser = params.get('currentUser')
    uid, enterpriseId = currentUser.get('uid'), currentUser.get('enterpriseId')
    if len(csvData) != len(mappedDataOfCsv):
        raise API_Error("Number of blanks data does not match with number of products.")
    try:
        titleField = int(mappedValues.get('title'))
        skuField = int(mappedValues.get('sku'))
        productStyleField = int(mappedValues.get('productStyle'))
        colorField = int(mappedValues.get('color'))
        sizeField = int(mappedValues.get('size'))
        imagesFields = list(mappedValues.get('images'))
        try:
            descriptionField = int(mappedValues.get('description'))
        except:
            descriptionField = None
        priceField = int(mappedValues.get('price')) if mappedValues.get('price') else None
    except Exception as e:
        print(traceback.format_exc())
        raise API_Error("Missing required fields to create products.", 400, dict(error=str(e)))
    products = {}
    blanks = {}
    skus = {}
    allprintingImages  = {}
    productSKUs = {}
    blankProducts = {}
    blankVariants = {}
    for row in csvData:
        rowNum = csvData.index(row)
        sku = row[skuField]
        title = str(row[titleField])
        print(sku, title)
        thisProductSKUs = productSKUs.get('title', [])
        if sku not in thisProductSKUs:
            thisProductSKUs.append(sku)
            productSKUs[title] = thisProductSKUs
        else:
            raise API_Error(f"Duplicate SKU found {sku} in {title}", 400, dict(rowNum=rowNum))
        color = str(row[colorField])
        size = str(row[sizeField])
        printingImages = []
        for field in imagesFields:
            try:
                url = row[int(field.get('image'))]
                fileName =f"{sku}{imagesFields.index(field)}.png"
                # res = requests.get(url)
                # if res.status_code == 200:
                #     path = get_file_path(fileName)
                #     with open(path, "wb") as file:
                #         file.write(res.content)
                #         # file = saveFile(
                #         #     uid=uid,
                #         #     enterpriseId=enterpriseId,
                #         #     fileName= fileName,
                #         #     source_file_name=path,
                #         #     type="printing"
                #         # )
                printingImages.append(dict(
                    id="MANUAL",
                    createdAt=datetime.now(),
                    uid=uid,
                    enterpriseId=enterpriseId,
                    url=url,
                    private=False,
                    name=fileName,
                    type="printing",
                    storageInfo = dict(
                        publicUrl=url,
                        bucketId = None,
                        name=fileName,
                    ),
                    placement=placementMapping.get(row[int(field.get('placement'))])
                ))
            except Exception as e:
                print(e)
                print(traceback.print_exc())
                raise API_Error("Images upload failed.", 400, dict(error=str(e)))
        allprintingImages[sku] = printingImages
        description = str(row[descriptionField]) if descriptionField else ""
        tags = []
        price = 0
        try:
            price = float(row[priceField])
        except:
            # print(f"Price should be valid number, found in product {title}", 400, dict(rowNum=rowNum))
            pass
        thisVariant =  convertVariant(
                id=sku,
                price=price,
                properties=[convertProperty(name="Color", value=color), convertProperty(name="Size", value=size)],
                sku=sku,
            )
        thisProductBlank = mappedDataOfCsv[rowNum]
        blankProductId, blankVariantId = thisProductBlank.get('blankProductId'), thisProductBlank.get('blankVariantId')
        if blankProductId not in blankProducts:
            blankProducts[blankProductId] = getBlankProduct(blankProductId)
        if blankProductId+blankVariantId not in blankVariants:
            blankVariants[blankProductId+blankVariantId] = getBlankVariant(blankProductId, blankVariantId)
        blankProduct, blankVariant = blankProducts.get(blankProductId), blankVariants.get(blankProductId+blankVariantId)
        blanks[sku] = blankProduct, blankVariant
        thisVariation = convertVariation(
            productName=title,
            color=color,
            size=size,
            images=printingImages,
            key=blankVariantId,
            nickName="",
            nickNameWithSize=size,
            price=price,
            sku=sku,
            variant=blankVariant
        )
        thisVariantMapping = convertVariantMapping(
            blankProductId=blankProductId,
            blankVariantId=blankVariantId,
            gtin=blankVariant.get('gtin'),
            id=sku,
            sku=sku,
            images = printingImages
        )
        thisProductVariants = skus.get(title, [])
        thisProductVariants.append((thisVariant, thisVariantMapping, thisVariation))
        skus[title] = thisProductVariants
        # thisProductVariants, thisVariantMappings, thisProductVariations = skus.get(sku, ([],[],[]))
        # thisProductVariants.append(thisVariant)
        # thisVariantMappings.append(thisVariantMapping)
        # thisProductVariations.append(thisVariation)
        # skus[title] = (thisProductVariants, thisVariantMappings, thisProductVariations)
        currentSkus = productSKUs.get(title, [])
        currentSkus.append(sku)
        productSKUs[title] = currentSkus
        now = datetime.now()
        if title not in products.keys():
            products[title] = convertProduct(
                uid = uid,
                platformId="0",
                shopId="0"+uid,
                enterpriseId=enterpriseId,
                platformProductId=str(int(now.timestamp())),
                price = price,
                name= title,
                description= description,
                createdAt=now,
                updatedAt=now,
                tags=tags,
                images = [],
                idRequired=False
            )
    savedProducts = []
    for title in products.keys():
        product = products.get(title)
        blankProductIds = []
        thisProductSKUs = productSKUs.get(title)
        variants = skus.get(title)
        print(title , len(variants))
        images = []
        for sku in thisProductSKUs:
            blankProduct, blankVariant = blanks.get(sku)
            blankProductIds.append(blankProduct.get('id'))
            images.extend(allprintingImages.get(sku))
        product['skus'] = [a.get("sku") for a,b,c in variants]
        imageIds = [i.get('id') for i in images]
        product['productMapping'] = convertProductMapping(
            blankProductIds=ArrayUnion(blankProductIds),
            enterpriseId=enterpriseId,
            imageIds=ArrayUnion(imageIds),
            uid=uid,
        )
        product['selectedBlankNicknames'] = []
        product['productDetails'] = dict(
            avatars=images,
            description=product.get('description'),
            tags=product.get('tags', []),
            title=title,
        )
        savedProducts.append((product,variants))

    for product in savedProducts:
        product, variants = product
        print(len(variants))
        id = saveManualProduct(product,variants)
        print(id)
    return savedProducts



def convertVariation(productName,nickName, nickNameWithSize,price, color, size, key,  sku, variant, images):
    return dict(
        productName=productName,
        nickName=nickName,
        nickNameWithSize=nickNameWithSize,
        price=price, 
        color=color, 
        size=size, 
        key=key,  
        sku=sku, 
        variant=variant, 
        images=images
    )

def convertVariantMapping(
    blankProductId,
    blankVariantId,
    gtin,
    id,
    sku,
    images
):
    return dict(
        blankProductId=blankProductId,
        blankVariantId=blankVariantId,
        gtin=gtin,
        id=id,
        sku=sku,
        images=images
    )

def convertProductMapping(
    blankProductIds,
    enterpriseId,
    uid,
    imageIds,
    printOnDemand=True,
    ignored=False,
):
    return dict(
        updatedAt =SERVER_TIMESTAMP,
        blankProductIds=blankProductIds,
        enterpriseId=enterpriseId,
        uid=uid,
        imageIds=imageIds,
        printOnDemand=printOnDemand,
        ignored=ignored,
    )