import os
from datetime import datetime

import pydash
import requests

from functions.LastUpdated import productsLastUpdated, saveProductsLastUpdated
from functions.Products import (convertImage, convertProduct, convertProperty,
                                convertVariant, saveProduct)
from functions.Shops import getShops
from functions.Storage import get_file_path, saveFile
from functions.Suppliers.BlankProducts import worker
from functions.WooCommerce import Auth
from V2.functions.Images.main import Image
from V2.functions.Products.main import Product
from V2.functions.Products.Variants import Property, Variant
from V2.functions.Shops.main import Shop
from V2.middlewares.auth import API_Error


def get_image(url):
    try:
        name = url.replace("/", "-")
        path = get_file_path(name)
        with open(path, 'wb') as f:
            f.write(requests.get(url).content)
        file = saveFile(uid=None, enterpriseId=None,fileName=name, source_file_name=path,type='product')
        os.remove(path)
        return file.get("url")
    except Exception as e:
        print(e)
        return url

def updateAllProducts(params={}):
    shops = getShops(platformId="3", credentials= True)
    res =  worker(updateShopProducts, shops)
    return str(res)

def updateShopProducts(shop):
    if shop:
        shopId = shop.get('id')
        updates = []
        uid = shop.get('uid')
        enterpriseId = shop.get('enterpriseId')
        consumerKey = shop.get("consumerKey")
        consumerSecret = shop.get("consumerSecret")
        url = shop.get('url')
        if not consumerKey or not consumerSecret:
            return updates
        lastUpdate = productsLastUpdated(shopId)
        platformId = shop.get("platformId")
        wcapi = Auth.wooAPI(url, consumerKey, consumerSecret)
        products = getProducts(wcapi, page=lastUpdate.get('nextPage'))
        if not products: return
        for product in products:
            convertedProduct = convertProduct(
                uid=uid,
                platformId=platformId,
                shopId=shopId,
                enterpriseId=enterpriseId,
                platformProductId=product.get('id'),
                name = product.get('name'),
                description= product.get('short_description'),
                createdAt= datetime.now(),
                updatedAt= datetime.now(),
                price = product.get('regular_price'),
                tags = product.get('tags', []),
                images = [convertImage(url = get_image(image.get('src')), id=  image.get('id')) for image in product.get('images', [])]
            )
            variants = getProductVariants(wcapi=wcapi, productId=product.get('id'))
            convertedVariants = [convertVariant(
                id = variant.get('id'),
                price = variant.get('price'),
                deleted = variant.get('status') != 'publish',
                imageId = variant.get('image', {}).get('id') if variant.get("image") else None,
                # ignore sku for app.myshirtpod.com
                sku = None if shop.get('enterpriseId') == "lJ2eUFov5WyPlRm4geCr" else  variant.get('sku'),
                properties= [convertProperty(
                    name=p.get('name'),
                    id = p.get('id'),
                    value = p.get('option')
                ) for p in variant.get('attributes', [])
                ]
            ) for variant in variants]
            updates.append(saveProduct(convertedProduct, convertedVariants))
        saveProductsLastUpdated(shopId, count = len(updates), lastPage=lastUpdate.get('nextPage'), nextPage=lastUpdate.get('nextPage') + 1 if len(updates) > 0 else 1)
        return f"Products updated => {len(updates)}"
    return "No updates"

def updateSingleProduct(shop:Shop,platformProductId:str):
    uid = shop.uid
    shopId = shop.id
    url = shop.url
    wcapi = Auth.wooAPI(url, shop.consumerKey, shop.consumerSecret)
    product = getProduct(wcapi, platformProductId)
    convertedProduct = Product(
            uid=uid,
            platformId=shop.platformId,
            shopId=shopId,
            enterpriseId=shop.enterpriseId,
            platformProductId=product.get('id'),
            name = product.get('name'),
            description= product.get('short_description'),
            createdAt= datetime.fromisoformat(product.get('date_created')),
            updatedAt= datetime.fromisoformat(product.get('date_modified')),
            price = product.get('regular_price'),
            tags = product.get('tags', []),
            images = [Image(url = get_image(image.get('src')), id=  image.get('id')) for image in product.get('images', [])]
        )
    variants = getProductVariants(wcapi=wcapi, productId=product.get('id'))
    convertedVariants = [Variant(
        id = variant.get('id'),
        price = variant.get('price'),
        deleted = variant.get('status') != 'publish',
        sku = variant.get('sku'),
        properties= [Property(
            name=p.get('name'),
            id = p.get('id'),
            value = p.get('option')
        ) for p in variant.get('attributes', [])
        ]
    ) for variant in variants]
    return convertedProduct.save(variants=convertedVariants)
    
def getProducts(wcapi, after=None, page=1):
    try:
        products = wcapi.get("products", params=dict(per_page=100,page=page, after=after))
        if products.status_code == 200:
            return products.json()
        else: print(products.status_code, products.text)
    except Exception as e:
        print(e)
    return None

def getProduct(wcapi, platformProductId:str):
    res = wcapi.get(f"products/{platformProductId}")
    if res.status_code == 200:
        return res.json()
    raise API_Error(res.text, res.status_code)

def getProductVariants(wcapi, productId):
    variants = wcapi.get(f"products/{productId}/variations?per_page=100")
    if variants.status_code == 200:
        return variants.json()
    print(variants.text)
    return []

def createAttributeTerms(wcapi,attributeId,terms=[]):
    data = {
    "create": [
        {
            "name": term
        } for term in terms
    ]
}
    res = wcapi.post(f"products/attributes/{attributeId}/terms/batch", data)
    if res.status_code in (200,201):
        return res.json().get("create")
    print(res.text)
    return {}

def createAttributes(wcapi, attribute):
    data = dict(
        name = attribute.get("name")
    )
    existingAttributesRes = wcapi.get("products/attributes")
    if existingAttributesRes.status_code == 200:
        existingAttributes ={ a.get("name"):a for a in existingAttributesRes.json()}
        if attribute.get("name") in existingAttributes:
            # terms = attribute.get("options")
            attributeId = existingAttributes.get(attribute.get("name")).get("id")
            # terms = createAttributeTerms(wcapi,attributeId,terms)
            return {attribute.get("name"):attributeId}
    res = wcapi.post("products/attributes", data)
    if res.status_code in (200,201):
        # terms = attribute.get("options")
        attributeId = res.json().get("id")
        # terms = createAttributeTerms(wcapi,attributeId,terms)
        return {attribute.get("name"): attributeId}
    print(res.text)
    return {}
def createVariants(wcapi,productId, variants=[]):
    # print(productId, json.dumps(
    #         variants, indent=2
    #     ))
    chunkedVariants = pydash.chunk(variants, 100)
    submittedVariants = {}
    for variations in chunkedVariants:
        data = {"create": variations}
        res = wcapi.post(f"products/{productId}/variations/batch", data)
        if res.status_code in (200,201): submittedVariants.update({v.get("sku"):v.get("id") for v in res.json().get("create")})
    return submittedVariants