import traceback
from datetime import datetime

import pytz

from configs.firebase import db
from V2.functions.Address.main import Address
from V2.functions.Applications.main import Application
from V2.functions.Images.main import Image
from V2.functions.LastUpdate import LastUpdate
from V2.functions.Orders.main import Order
from V2.functions.Orders.OrderItem import OrderItem
from V2.functions.Products.Variants import Property, Variant
from V2.functions.Shops.main import Shop, getShopsByPlatformId
from V2.functions.Squarespace.Auth import SquarespaceClient
from V2.middlewares.auth import API_Error
from V2.Params import Params


def updateAllOrders(params:Params):
    shops = getShopsByPlatformId(platformId="10", credentials= True)
    return str([updateShopOrders(shop) for shop in shops])

def updateShopOrders(shop:Shop):
    try:
        shopId = shop.id
        updates:list[str] = []
        application = Application.get(shop.appId)
        lastUpdate = LastUpdate.get(shopId)
        client = SquarespaceClient(application, shop)
        orders, pagination = getOrders(client=client,lastUpdated=lastUpdate)
        for order in orders:
            platformOrderId = order.get('id')
            items:list[dict] = order.get("lineItems",[])
            orderItems:list[OrderItem]= []
            createdAt, updatedAt = datetime.strptime(order.get("createdOn"), "%Y-%m-%dT%H:%M:%S.%fZ"),datetime.strptime(order.get("modifiedOn"), "%Y-%m-%dT%H:%M:%S.%fZ"),
            shippingAddress = order.get("shippingAddress", order.get("billingAddress"))
            billingAddress = order.get("billingAddress")
            address = shippingAddress if shippingAddress else billingAddress
            if not address: continue 
            for item in items:
                orderItem = OrderItem(
                    uid=shop.uid,
                    enterpriseId=shop.enterpriseId,
                    platformId=shop.platformId,
                    platformProductId= item.get('productId'),
                    platformOrderItemId=item.get('id'),
                    platformOrderId = platformOrderId,
                    quantity = item.get('quantity'),
                    price = float(item.get('unitPricePaid', {}).get("value")),
                    discount = 0,
                    tax=0,
                    subtotal=float(item.get('unitPricePaid', {}).get("value"))*item.get("quantity"),
                    total=float(item.get('unitPricePaid', {}).get("value"))*item.get("quantity"),
                    variantId= str(item.get('variantId')),
                    name=item.get('productName'),
                    shopId=shopId, 
                    createdAt= createdAt,
                    updatedAt= updatedAt,
                    image=Image(url=item.get("imageUrl")),
                    productId=shop.platformId+shop.id+str(item.get("productId"))
                )
                variations = item.get('variantOptions', []) if item.get('variantOptions', []) else []
                customizations = item.get("customizations", []) if item.get("customizations", []) else []
                orderItem.addVariant(
                    Variant(
                        id=item.get('variantId'),
                        price=orderItem.price,
                        sku=item.get("sku"),
                        properties=[
                        Property(
                            name = variation.get('optionName'),
                            value = variation.get('value')
                        ) for variation in variations
                        ]+[Property(
                            name=p.get("label"),
                            value=p.get("value") 
                        ) for p in customizations] 
                    )
                )
                orderItems.append(orderItem)
            convertedOrder = Order(
                uid=shop.uid,
                platformId=shop.platformId,
                shopId=shopId,
                enterpriseId=shop.enterpriseId,
                cancelled=order.get('fulfillmentStatus') == "CANCELED",
                draft=False,
                shippingAddress=Address(
                    name=f"{address.get('firstName')} {address.get('lastName')}",
                    address1= address.get('address1'),
                    address2= address.get('address2'),
                    city = address.get('city'),
                    state = address.get('state'),
                    zip = address.get('postalCode'),
                    country = address.get('countryCode'),
                    countryCode= address.get('country_iso'),
                    phone=address.get('phone'),
                ),
                platformOrderId=platformOrderId, 
                createdAt = createdAt,
                updatedAt= updatedAt,
                shipped= order.get('fulfillmentStatus') == "FULFILLED",
                grandTotal= order.get('grandTotal').get("value"),
                currencyCode= order.get("grandTotal").get('currency'),
                shippingCost= order.get('shippingTotal').get("value"),
                totalDiscount= order.get('discountTotal').get("value"),
                totalTax= order.get('taxTotal').get("value"),
                totalPrice= sum([item.price for item in orderItems]),
                shopName=shop.name,
            )
            updates.append(convertedOrder.save(orderItems))
        lastUpdate.save(count=len(updates), nextPage=pagination.get("nextPageCursor"))
        return lastUpdate
    except Exception as e:
        # print(traceback.format_exc())
        return str(e)

def updateSingleOrder(shop:Shop, platformOrderId: str, readd=True):
    try:
        shopId=shop.id
        app = Application.get(shop.appId)
        client = SquarespaceClient(app, shop)
        order = getOrder(client,platformOrderId)
        # print(order)
        if order:
            items = order.get("lineItems")
            orderItems = []
            createdAt, updatedAt = datetime.strptime(order.get("createdOn"), "%Y-%m-%dT%H:%M:%S.%fZ"),datetime.strptime(order.get("modifiedOn"), "%Y-%m-%dT%H:%M:%S.%fZ"),
            for item in items:
                orderItem = OrderItem(
                    uid=shop.uid,
                    enterpriseId=shop.enterpriseId,
                    platformId=shop.platformId,
                    platformProductId= item.get('productId'),
                    platformOrderItemId=item.get('id'),
                    platformOrderId = platformOrderId,
                    quantity = item.get('quantity'),
                    price = item.get('unitPricePaid', {}).get("value", 0),
                    discount = 0,
                    tax=0,
                    subtotal=item.get('subtotal', {}).get("value", 0),
                    total=item.get('price', {}).get("amount", 0)/item.get('price', {}).get("divisor", 1)*item.get('quantity',1),
                    variantId= str(item.get('variantId')),
                    name=item.get('productName'),
                    shopId=shopId, 
                    createdAt= createdAt,
                    updatedAt= updatedAt,
                    image=Image(url=item.get("imageUrl")),
                    # image=Image.from_dict(getListingImage(client,str(item.get("listing_id")),str(item.get("listing_image_id")))),/
                    productId=shop.platformId+shop.id+str(item.get("productId"))
                )
                variations = item.get('variantOptions', [])
                orderItem.addVariant(
                    Variant(
                        id=item.get('product_id'),
                        price=orderItem.price,
                        sku=item.get("sku"),
                        properties=[
                        Property(
                            name = variation.get('optionName'),
                            # id = variation.get('property_id'),
                            value = variation.get('value')
                        ) for variation in variations
                        ]
                    )
                )
                orderItems.append(orderItem)

            shippingAddress = order.get("shippingAddress")
            convertedOrder = Order(
                uid=shop.uid,
                platformId=shop.platformId,
                shopId=shopId,
                enterpriseId=shop.enterpriseId,
                cancelled=False,
                draft=False,
                shippingAddress=Address(
                    name=f"{shippingAddress.get('firstName')} {shippingAddress.get('lastName')}",
                    address1= shippingAddress.get('address1'),
                    address2= shippingAddress.get('address2'),
                    city = shippingAddress.get('city'),
                    state = shippingAddress.get('state'),
                    zip = shippingAddress.get('postalCode'),
                    country = shippingAddress.get('countryCode'),
                    countryCode= shippingAddress.get('countryCode'),
                    # email=shippingAddress.get('buyer_email'),
                ),
                platformOrderId=platformOrderId, 
                createdAt = createdAt,
                updatedAt= updatedAt,
                grandTotal= order.get('grandTotal').get("value"),
                shipped= order.get('fulfillmentStatus') == "FULFILLED",
                currencyCode= order.get("grandTotal", {}).get('currency',"USD"),
                shippingCost= order.get('shippingTotal').get("value"),
                totalDiscount= order.get('discountTotal').get("value"),
                totalTax= order.get('taxTotal').get("value"),
                totalPrice= order.get('subtotal').get("value"),
                shopName=shop.name,
            )
            return dict(id=convertedOrder.save(orderItems, rewrite=True, readd=readd))
    except Exception as e:
        raise API_Error(str(e))    

def getOrders(client: SquarespaceClient, lastUpdated:LastUpdate) -> tuple[list, dict]:
    url = f"https://api.squarespace.com/{client.shop.apiVersion}/commerce/orders"
    res = client.get(
        url, 
        params=dict(
            modifiedAfter=f'{datetime.fromtimestamp(lastUpdated.timestamp - 86400, tz=pytz.utc).strftime("%Y-%m-%dT%H:%M:%S")}Z',
            modifiedBefore=f'{datetime.now(tz=pytz.utc).strftime("%Y-%m-%dT%H:%M:%S")}Z',
            cursor=lastUpdated.nextPage if type(lastUpdated.nextPage) == str else None
        )
    )
    # print(res.text)
    if res.status_code == 200: return res.json().get("result", []), res.json().get("pagination")
    return [],{}

def getOrder(client: SquarespaceClient, platformOrderId: str):
    url = f"https://api.squarespace.com/1.0/commerce/orders/{platformOrderId}"
    res = client.get(url)
    # print(res.text)
    if res.status_code == 200: return res.json()
    return None

# def submitShipment(shop:Shop, platformOrderId:str, trackingCode:str, carrierName:str):
#     app = Application.get(shop.appId)
#     client = SquarespaceClient(app.apiKey,shop)
#     url = f"https://openapi.etsy.com/v3/application/shops/{shop.platformShopId}/receipts/{platformOrderId}/tracking"
#     res = client.post(
#         url=url, 
#         data=dict(
#             carrier_name=carrierName,
#             tracking_code=trackingCode,
#             send_bcc=True
#         )
#     )
#     if res.status_code == 200: return True
#     print(res.text, res.status_code)
#     return False

def submitShipment(shop: Shop, platformOrderId:str, trackingCode:str, carrierName:str,carrierService:str, **kwargs):
    app = Application.get(shop.appId)
    client = SquarespaceClient(shop=shop, app=app)
    url = f"https://api.squarespace.com/1.0/commerce/orders/{platformOrderId}/fulfillments"
    payload = dict(
        shouldSendNotification=True,
        shipments = [
            dict(
                shipDate = f"{datetime.now(tz=pytz.timezone(shop.timezone)).strftime('%Y-%m-%dT%H:%M:%S')}Z",
                carrierName=carrierName,
                service=carrierService,
                trackingNumber=trackingCode,
                trackingUrl=kwargs.get("trackingUrl"),
            )
        ]
    )
    # print(payload)
    response = client.post(url, data=payload)
    # print(response.text)
    if response.ok: return response.json()
    raise API_Error(response.text, response.status_code)

# submitShipment(Shop.get("BMhT81AqDeaynGQATP4j"), "667b1df6e2636e1fe7228a8f", "123", "USPS", "Priority")