from datetime import datetime

from configs.firebase import SERVER_TIMESTAMP, db
from functions.Response import API_Error
from functions.Shops import getUserShops
from functions.Suppliers.BlankProducts import removehtml
from V2.functions.Shops.main import Shop


def convertProduct(
        uid:str, 
        platformId:str, 
        shopId:str, 
        enterpriseId:str, 
        platformProductId:str, 
        name:str, 
        description:str,
        createdAt:datetime, 
        updatedAt:datetime,
        price = None,
        tags=[],
        images=[],
        idRequired = True,**kwargs
        ):
    platformProductId = str(platformProductId)
    product = dict(
        id = getProductRef(platformId,shopId,platformProductId) if idRequired else None, 
        uid=uid, 
        platformId=platformId, 
        shopId=shopId, 
        enterpriseId=enterpriseId, 
        platformProductId=str(platformProductId),
        name=str(name), 
        description=removehtml(description),
        createdAt=createdAt, 
        updatedAt=updatedAt,
        price=float(price) if price else price,
        tags=list(tags),
        images=list(images),**kwargs
    )
    return product

def convertImage(url:str, id=None, primary=False):
    return dict(url=url, id=str(id) if id else id, primary=primary)

def convertProperty(name, value, id=None):
    p = dict(
        name = str(name),
        value = str(value),
        id = str(id) if id else id
    )
    return p

def convertVariant(
        id:str, 
        # productId:str, 
        # platformVariantId:str,
        # name:str, 
        price=0, 
        properties = [], 
        deleted=False, 
        imageId=None, 
        sku=None,
        images=[],
        **kwargs
        ):
    if sku in ["None", "Null", "null", "none"]: sku = None
    if "/" in str(id): id = str(id).replace("/", "-")
    variant = dict(
        id=str(id),
        # productId=str(productId),
        # platformVariantId=str(platformVariantId),
        # name=str(name),
        properties=list(properties),
        price=float(price) if price else price,
        deleted=bool(deleted),
        imageId=str(imageId) if imageId else imageId,
        sku=str(sku) if sku else sku,
        updatedAt = SERVER_TIMESTAMP,
        images=images
    )
    if kwargs: variant.update(kwargs)
    return variant

def saveProduct(product, variants):
    ref = db.collection("products").document(product.get('id'))
    ref.set(product, merge=True)
    variantsRef = ref.collection("variants")
    existingVariantIds = [variant.id for variant in variantsRef.get()]
    currentVariantIds = [variant.get('id') for variant in variants]
    deletedVariants = findDifferenceInTwoLists(existingVariantIds, currentVariantIds)
    for variant in deletedVariants:
        variantsRef.document(variant).update(dict(deleted=True, updatedAt = SERVER_TIMESTAMP))
    for variant in variants:
        variant['productId'] = product.get('id')
        variantsRef.document(variant.get('id')).set(variant, merge=True)
    return ref.id

def findDifferenceInTwoLists(list1, list2):
    return [item for item in list1 if item not in list2]

def getProductRef(platformId, shopId , platformProductId):
    return platformId+shopId+platformProductId

def findProduct(uid, platformId, platformProductId, shopId=None):
    if shopId:
        ref = db.collection("products").where('platformProductId', "==", platformProductId).where('uid', '==', uid).where('platformId', '==', platformId).where("shopId", "==", shopId).get()
        if len(ref)>0:return ref[0].to_dict()
    else:
        ref = db.collection("products").where('platformProductId', "==", platformProductId).where('uid', '==', uid).where('platformId', '==', platformId).get()
        if len(ref)>0:
            return ref[0].to_dict()
    return {}

def getProductById(productId):
    ref = db.collection("products").document(productId).get()
    print(ref.reference.path)
    if ref.exists:
        return ref.to_dict()
    else: print("Product not found")
    return {}

def getProductBySku(uid, sku):
    ref = db.collection("manualProducts").where('uid','==', uid).where('skus', 'array_contains', sku).get()
    if len(ref)>0:
        thisref = ref[0]
        variant = thisref.reference.collection('variants').document(sku).get()
        variantsMapping = thisref.reference.collection('variantsMapping').document(sku).get()
        return thisref.to_dict(), variant.to_dict(), variantsMapping.to_dict()
    raise API_Error(f"Product not found for sku {sku}", 404)

def getProductVariant(productId, variantId):
    productId, variantId = str(productId), str(variantId)
    ref = db.collection("products").document(productId).collection("variants").document(variantId).get()
    if ref.exists: return ref.to_dict()
    return {}

def getProductVariantByPlatformId(platformProductId, platformVariantId):
    product = db.collection("products").where('platformProductId', "==", platformProductId).get()
    if product:
        product = product[0]
        variant = db.collection("products").document(product.id).collection("variants").document(platformVariantId).get()
        return variant.to_dict()
    return None

def getProductVariants(productId) -> list[dict]:
    ref = db.collection("products").document(productId).collection("variants").get()
    return [r.to_dict() for r in ref]

def getProductsMapping(productId, variantId =None):
    ref = db.collection("productsMapping").document(productId).get()
    if ref.exists:
        mapping = ref.to_dict()
        if variantId: return mapping, getVariantMapping(productId, variantId)
        return mapping , {}
    return {}, {}

def getProductVariantsMapping(productId):
    ref = db.collection("productsMapping").document(productId).get()
    if ref.exists:
        mapping = ref.to_dict()
        return mapping , [v.to_dict() for v in ref.reference.collection("variantsMapping").get()]
    return None

def getVariantMapping(productId, variantId):
    ref = db.collection("productsMapping").document(productId).collection("variantsMapping").document(variantId).get()
    if ref.exists: return ref.to_dict()
    else:
        ref = db.document(f"manualProducts/{productId}/variantsMapping/{variantId}").get()
        if ref.exists: return ref.to_dict()
    return {}

def getManualProductById(productId):
    ref = db.collection("manualProducts").document(productId).get()
    if ref.exists:
        return ref.to_dict()
    return None

def getManualProductVariant(productId, variantId):
    productId, variantId = str(productId), str(variantId)
    ref = db.collection("manualProducts").document(productId).collection("variants").document(variantId).get()
    if ref.exists: return ref.to_dict()
    return None

def getColorImages(productId, blankProductId=None, blankVariantId=None):
    if not (blankProductId or blankVariantId): return []
    blankVariant = db.document(f"blankProducts/{blankProductId}/blankVariants/{blankVariantId}").get()
    color = None
    if blankVariant.exists: 
        color = blankVariant.to_dict().get("color")
        color = str(color).replace("/", "-")
    ref = db.document(f"manualProducts/{productId}/colorImages/{color}").get()
    if not ref.exists: ref = db.document(f"productsMapping/{productId}/colorImages/{color}").get()
    if ref.exists: return ref.to_dict().get("images", [])
    if blankProductId:
        ref = db.document(f"productsMapping/{productId}/placements/{blankProductId}").get()
        if ref.exists:
            previewImages = ref.to_dict().get("previewImages", {}).get(color, {})
            if previewImages: return [
                dict(
                    id=value.get("id"),
                    url=value.get("url"),
                    placement=key,
                ) for key,value in previewImages.items()
            ]
    return []


from functions.Shopify.Products import \
    updateShopProducts as updateUserShopifyProducts
from functions.Square.Products import \
    updateShopProducts as updateUserSquareProducts
from functions.WooCommerce.Products import \
    updateShopProducts as updateUserWoocommerceProducts
from V2.functions.Bigcartel.Products import \
    updateShopProducts as updateUserBigcartelProducts
from V2.functions.Etsy.Products import \
    updateShopProducts as updateUserEtsyProducts
from V2.functions.Squarespace.Products import \
    updateShopProducts as updateUserSquarespaceProducts


def updateUserProducts(params):
    uid = params.get('currentUser').get('uid')
    shops = getUserShops(uid, True)
    response  = {
        "Etsy": [updateUserEtsyProducts(Shop.from_dict(shop)) for shop in shops if shop.get('platformId') == "1"],
        "Shopify": [updateUserShopifyProducts(shop) for shop in shops if shop.get('platformId') == "2"],
        "WooCommerce": [updateUserWoocommerceProducts(shop) for shop in shops if shop.get('platformId') == "3"],
        "Square": [updateUserSquareProducts(shop) for shop in shops if shop.get('platformId') == "4"],
        "Squarespace": [updateUserSquarespaceProducts(Shop.from_dict(shop)) for shop in shops if shop.get('platformId') == "10"],
        "Bigcartel": [updateUserBigcartelProducts(Shop.from_dict(shop)) for shop in shops if shop.get('platformId') == "8"],
    }
    return response

