

import concurrent.futures
from datetime import datetime

import pytz
import requests

from configs.firebase import Increment, db
from functions.Orders import (convertOrder, convertOrderItem,
                              convertShippingAddress, saveOrder)
from functions.Shopify.Auth import apiVersion, createHeader
from V2.functions.Address.main import Address
from V2.functions.Orders.main import (Order, OrderItem,
                                      findOrderByPlatformOrderId)
from V2.functions.Shops.main import Shop, getShopsByPlatformId, getUserShops
from V2.Params import Params


def verifyShopifyDailyOrders(params:Params):
    shops = getShopsByPlatformId("2", True)
    updates = []
    start,end = params.args.get("start"), params.args.get("end")
    if( start and end) or params.currentUser:
        shops = getUserShops(params.currentUser.uid)
        shops = [shop for shop in shops if shop.platformId == "2" if not shop.disabled]
    for shop in shops:
        updates.append(verifyDailyOrders(shop, start, end))
    return updates

def verifyDailyOrders(shop:Shop, start=None, end=None):
        shopId  = shop.id
        accessToken = shop.accessToken
        url = shop.url
        headers = createHeader(accessToken)
        ordersUrl = f"{url}/admin/api/{apiVersion}/orders.json"
        nowTimestamp = datetime.now(tz=pytz.utc).isoformat()
        yesterdayTimestamp = datetime.fromtimestamp(datetime.now(tz=pytz.utc).timestamp() - 86400*3).isoformat()
        if start and end:
            yesterdayTimestamp = datetime.fromtimestamp(int(start)).isoformat()
            nowTimestamp = datetime.fromtimestamp(int(end)).isoformat()
        try:
            res = requests.get(ordersUrl, headers=headers, params=dict(created_at_min=yesterdayTimestamp,created_at_max=nowTimestamp,status="any",financial_status="paid",limit=250))
            print(res.text)
            if res.status_code != 200:
                print(res.text)
                return None
            orders:list[dict] =  []
            endpoint = None
            if res.status_code == 200:
                orders.extend(res.json().get('orders', []))
                Link:str|None = res.headers.get("Link")
                if Link:
                    nextPage = Link.endswith('rel="next"')
                    while Link and nextPage:
                        endpoint = Link.replace("<", "").replace('>; rel="next"', "")
                        request = requests.get(endpoint, headers=headers)
                        if request.status_code == 200:
                            data = request.json()
                            orders.extend(data.get('orders', []))
                            Link = request.headers.get("Link")
                            nextPage = Link.endswith('rel="next"')
                        else:
                            print(request.text)
                            return None
            notFoundOrders = []
            if orders:
                with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
                    notFoundOrders = list(executor.map(lambda args: addNotFoundOrder(*args), [(shop, order) for order in orders], chunksize=10))
                # for order in orders:
                #     found = findOrderByPlatformOrderId(shopId, str(order.get('id')))
                #     print(str(order.get('id')), bool(found))
                #     if not found: notFoundOrders.append(addShopifyOrder(order, shop))
            print("Added not found orders for shop", shop.id, notFoundOrders)
            return notFoundOrders
        except Exception as e:
            print(e)
            return None
        
def addNotFoundOrder(shop, order):
    found = findOrderByPlatformOrderId(shop.id, str(order.get('id')))
    if not found: return addShopifyOrder(order, shop)

def addShopifyOrder(order:dict, shop:Shop):
    shipping_address = order.get('shipping_address', {})
    ignoredItems = []
    shipping_address = order.get('shipping_address', {})
    source_name = order.get('source_name')
    tags = []
    if source_name in ["4919179", "2329312", "4555605"]: 
        source_name = f"{shop.name} - tiktok"
        tags.append(source_name)
    if shipping_address:
        convertededOrder = convertOrder(
            uid=shop.uid,
            platformId=shop.platformId,
            shopId= shop.id,
            enterpriseId=shop.enterpriseId,
            shippingAddress=convertShippingAddress(
                name = shipping_address.get('name'), 
                address1= shipping_address.get('address1'),
                address2= shipping_address.get('address2'),
                city= shipping_address.get('city'),
                state= shipping_address.get('province'),
                zip= shipping_address.get('zip'),
                country= shipping_address.get('country'),
                email= order.get('email'),
                phone= order.get('phone'),
                company= shipping_address.get('company'),
            ),
            cancelled =bool(order.get("cancelled_at")),
            shipped= order.get('fulfillment_status') == "fulfilled",
            createdAt= datetime.fromisoformat(order.get('created_at')),
            updatedAt= datetime.fromisoformat(order.get('updated_at')),
            currencyCode= order.get('currency'),
            platformOrderId= order.get('id'),
            grandTotal= order.get('total_price'),
            shippingCost= order.get('total_shipping_price_set', {}).get('shop_money', {}).get('amount', 0),
            totalDiscount= order.get('total_discounts'),
            totalPrice= order.get('total_price'),
            totalTax= order.get('total_tax'),
            orderNumber = str(order.get('order_number')),
            shopName = shop.name,
            metadata=dict(
                tags=tags
            ),
        )
        items = order.get('line_items', [])
        props = {str(item.get("id")):{prop.get("name"):prop.get("value") for prop in item.get('properties', [])} for item in items}
        variantMappings = {}
        blankVariants = {}
        if shop.id == "lJ2eUFov5WyPlRm4geCr": 
            for item in items:
                if item.get("vendor") != "MSP": ignoredItems.append(item.get("id"))
                if str(item.get("product_id")) == "4683530141765": tags.append("Skip the line")
        if props:
            for key, value in props.items():
                _placementsDocumentId = value.get("_placementsDocumentId")
                if _placementsDocumentId:
                    data = db.collection("shopifyCartPlacements").document(_placementsDocumentId).get().to_dict()
                    if data:
                        convertedOrderItems = convertCustomizerItems(
                            order,
                            data, 
                            shop,
                        )
                        # props[key] = data
                        # placementDetails= dict(data.get("placementDetails"))
                        # blankProductId = str(list(placementDetails.keys())[0])
                        # printFiles= placementDetails.get(blankProductId, {}).get("canvasImages", {}).get("default", {}).items()
                        # blankVariants.update({str(variant.get("platformVariantId")):(variant.get("blankVariantId") if variant.get("blankVariantId")  else variant.get("id") )for variant in data.get("variants", [])})
                        # images = [
                        #         dict(placement = str(k),**v)
                        #         for k,v in printFiles
                        #     ]
                        # variantMapping = dict(
                        #     id=str(key),
                        #     blankProductId = blankProductId,
                        #     # blankVariants=blankVariants,
                        #     # blankVariantId = next(variant.get("blankVariantId") for variant in data.get("variants") if variant.get("platformVariantId") == key),
                        #     images = images,
                        #     ignored=False,
                        #     placements = [i.get("placement") for i in images],
                        #     mapped="mapped",
                        #     productId=str(data.get("parentProductId")),
                        # )
                        # variantMappings[key] = variantMapping
                        # blankVariants.update({key: data.get("variants")[0].get("id")})
                        # print(variantMapping, blankVariants)
                        # data['blankVariants'] = blankVariants
                        # props[key] = dict(variantMapping, placementsData = data)

        # print(blankVariants)
        # print([item.get("variant_id") for item in items])
        convertedOrderItems = [convertOrderItem(
                uid = shop.uid,
                platformId = shop.platformId,
                enterpriseId=shop.enterpriseId,
                platformOrderItemId= item.get('id'),
                platformOrderId = order.get('id'),
                shopId=shop.id,
                cancelled=bool(order.get("cancelled_at")),
                createdAt= datetime.fromisoformat(order.get('created_at')),
                updatedAt= datetime.fromisoformat(order.get('updated_at')),
                name= item.get('name'),
                platformProductId= item.get('product_id'),
                price= item.get('price'),
                quantity= item.get('quantity'),
                shipped= item.get('fulfillment_status') == 'fulfilled',
                variantId= item.get('variant_id'),
                variantProperties={p.get("name"):p.get("value") for p in item.get('properties', [])},
                placementsData = props.get(str(item.get('id')), {}),
                productMapping = dict(printOnDemand=True, ignored=False) if props.get(str(item.get('id')), {}) and  blankVariants.get(str(item.get("variant_id"))) else None,
                variantMapping=dict(blankVariantId = blankVariants.get(str(item.get("variant_id"))),**variantMappings.get(str(item.get('id')), {})) if props.get(str(item.get('id'))) and blankVariants.get(str(item.get("variant_id"))) else {},
                ignored=item.get("id") in ignoredItems,
            ) for item in items
            ]
        return saveOrder(convertededOrder, convertedOrderItems)


# def addShopifyOrder(order:dict, shop:Shop):
#     shipping_address = order.get('shipping_address', {})
#     if shipping_address:
#         convertededOrder = Order(
#             uid=shop.uid,
#             platformId=shop.platformId,
#             shopId= shop.id,
#             enterpriseId=shop.enterpriseId,
#             shippingAddress=Address(
#                 name = shipping_address.get('name'), 
#                 address1= shipping_address.get('address1'),
#                 address2= shipping_address.get('address2'),
#                 city= shipping_address.get('city'),
#                 state= shipping_address.get('province'),
#                 zip= shipping_address.get('zip'),
#                 country= shipping_address.get('country'),
#                 email= order.get('email'),
#                 phone= order.get('phone'),
#                 countryCode= shipping_address.get('country_code'),
#             ),
#             cancelled =bool(order.get("cancelled_at")),
#             shipped= order.get('fulfillment_status') == "fulfilled",
#             createdAt= datetime.fromisoformat(order.get('created_at')),
#             updatedAt= datetime.fromisoformat(order.get('updated_at')),
#             currencyCode= order.get('currency'),
#             platformOrderId= order.get('id'),
#             grandTotal= order.get('total_price'),
#             shippingCost= order.get('total_shipping_price_set', {}).get('shop_money', {}).get('amount', 0),
#             totalDiscount= order.get('total_discounts'),
#             totalPrice= order.get('total_price'),
#             totalTax= order.get('total_tax'),
#             orderNumber = str(order.get('order_number')),
#             shopName = shop.get('name'),
#             draft=False
#         )
#         items = order.get('line_items', [])
#         props = {str(item.get("id")):{prop.get("name"):prop.get("value") for prop in item.get('properties', [])} for item in items}
#         variantMappings = {}
#         blankVariants = {}
#         if props:
#             for key, value in props.items():
#                 _placementsDocumentId = value.get("_placementsDocumentId")
#                 if _placementsDocumentId:
#                     data = db.collection("shopifyCartPlacements").document(_placementsDocumentId).get().to_dict()
#                     if data:
#                         props[key] = data
#                         placementDetails= dict(data.get("placementDetails"))
#                         blankProductId = str(list(placementDetails.keys())[0])
#                         printFiles= placementDetails.get(blankProductId, {}).get("canvasImages", {}).get("default", {}).items()
#                         blankVariants.update({str(variant.get("platformVariantId")):(variant.get("blankVariantId") if variant.get("blankVariantId")  else variant.get("id") )for variant in data.get("variants", [])})
#                         images = [
#                                 dict(placement = str(k),**v)
#                                 for k,v in printFiles
#                             ]
#                         variantMapping = dict(
#                             id=str(key),
#                             blankProductId = blankProductId,
#                             images = images,
#                             ignored=False,
#                             placements = [i.get("placement") for i in images],
#                             mapped="mapped",
#                             productId=str(data.get("parentProductId")),
#                         )
#                         variantMappings[key] = variantMapping
#         convertedOrderItems = [OrderItem(
#                 uid = shop.uid,
#                 platformId = shop.platformId,
#                 enterpriseId=shop.enterpriseId,
#                 platformOrderItemId= item.get('id'),
#                 platformOrderId = order.get('id'),
#                 shopId=shop.id,
#                 cancelled=bool(order.get("cancelled_at")),
#                 createdAt= datetime.fromisoformat(order.get('created_at')),
#                 updatedAt= datetime.fromisoformat(order.get('updated_at')),
#                 name= item.get('name'),
#                 platformProductId= item.get('product_id'),
#                 price= item.get('price'),
#                 quantity= item.get('quantity'),
#                 shipped= item.get('fulfillment_status') == 'fulfilled',
#                 variantId= item.get('variant_id'),
#                 purchaseOrderData=dict(blankVariantId = blankVariants.get(str(item.get("variant_id"))),**variantMappings.get(str(item.get('id')), {})) if props.get(str(item.get('id'))) and blankVariants.get(str(item.get("variant_id"))) else {},
#                 image={},
#                 discount= item.get('total_discount'),
#                 subtotal= float(item.get('price'))*item.get('quantity'),
#                 total= float(item.get('price'))*item.get('quantity'),
#                 tax=0
#             ) for item in items
#             ]
#         convertededOrder.save(convertedOrderItems, True)



def convertCustomizerItems(order:dict, data:dict,shop:Shop):
    placementDetails= dict(data.get("placementDetails"))
    blankProductId = str(list(placementDetails.keys())[0])
    variantType = "color"
    variantType = placementDetails.get(blankProductId, {}).get("variantType")
    canvasImages = placementDetails.get(blankProductId, {}).get("canvasImages", {})
    printImages = []
    for key, canvasImage in canvasImages.items():
        for placement, printImage in canvasImage.items():
            printImages.append(
                    dict(
                        id = printImage.get("id"),
                        placement = placement,
                        # variantTypeValue = key,
                        # variantType = variantType,
                        url = printImage.get("url"),
                        name = printImage.get("name"),
                        **{variantType: key}
                    )
            )
    variants = data.get("variants")
    variations = data.get("variations")
    variantType = placementDetails.get(blankProductId, {}).get("variantType", "color")
    source_name = order.get('source_name')
    if source_name in ["4919179", "2329312", "4555605"]: source_name = f"{shop.name} - tiktok"
    convertedOrderItems = []
    for item in order.get("line_items", []):
        variantId = item.get("variant_id")
        variant = next((v for v in variants if str(v.get("platformVariantId")) == str(variantId)), None)
        variation = next((v for v in variations if str(v.get("varId")) == str(variant.get("varId"))), None)
        thisItemPrintImages = [i for i in printImages if i.get(variantType) == variation.get(variantType)]
        if len(thisItemPrintImages) == 0:  thisItemPrintImages = [i for i in printImages if i.get(variantType) == "default"]
        blankVariantId = variant.get("blankVariantId") if variant.get("blankVariantId")  else variant.get("id")
        convertedOrderItem = convertOrderItem(
                        uid = shop.uid,
                        platformId = "2",
                        enterpriseId=shop.enterpriseId,
                        platformOrderItemId= item.get('id'),
                        platformOrderId = order.get('id'),
                        shopId=shop.id,
                        cancelled=bool(order.get("cancelled_at")),
                        createdAt= datetime.fromisoformat(order.get('created_at')),
                        updatedAt= datetime.fromisoformat(order.get('updated_at')),
                        name= item.get('name'),
                        platformProductId= item.get('product_id'),
                        price= item.get('price'),
                        quantity= item.get('quantity'),
                        shipped= item.get('fulfillment_status') == 'fulfilled',
                        variantId= item.get('variant_id'),
                        # variantProperties={p.get("name"):p.get("value") for p in item.get('properties', [])},
                        # placementsData = props.get(str(item.get('id')), {}),
                        productMapping = dict(
                                    printOnDemand=True, 
                                    ignored=False,
                                    decorationType=data.get("product").get("decorationType"),
                                ),
                        variantMapping=dict(
                            blankProductId=blankProductId,
                            blankVariantId = blankVariantId,
                            images=thisItemPrintImages,
                            placements=[i.get("placement") for i in thisItemPrintImages],
                        variantProperties=[
                            dict(
                                name = p.get("name"),
                                value = p.get("value")
                            ) for p in item.get("properties", [])
                        ],
                        metadata=dict(
                            tags = [source_name]
                    )
            ))
        convertedOrderItems.append(convertedOrderItem)
    return convertedOrderItems