


from datetime import datetime

import requests

from configs.firebase import SERVER_TIMESTAMP, db
from functions.Shipments.Main import submitShipmentToPlatform
from V2.functions.Address.main import Address
from V2.functions.Applications.main import Application
from V2.functions.LastUpdate import LastUpdate
from V2.functions.Orders.main import Order, OrderItem
from V2.functions.Products.main import Product
from V2.functions.Products.Variants import Image, Property, Variant
from V2.functions.Settings.main import getDecorationTypes, getPlacementOptions
from V2.functions.Shipments.main import Shipment
from V2.functions.Shops.main import Shop, getShopsByPlatformId
from V2.functions.Users.main import User
from V2.middlewares.auth import API_Error
from V2.Params import Params


def updateAllOrders(params:Params):
    shops = getShopsByPlatformId(platformId="12", credentials= True)
    # shops = [s for s in shops if all([s.apiVersion == "v3",s.accessToken, s.tokenType, s.expiresAt])]
    for shop in shops:
        try: updateShopOrders(shop)
        except Exception as e:print(e)
    return ""

def updateShopOrders(shop:Shop):
        shopId = shop.id
        updates:list[str] = []
        lastUpdate = LastUpdate.get(shopId)
        orders = getOrders(
            storeId=shop.platformShopId,
            apiKey=shop.apiKey,
            lastUpdated=lastUpdate.timestamp
        )
        orders.sort(key=lambda x: x.get('date_updated'))
        for order in orders:
                platformOrderId:str = order.get('id')
                metadata = order.get("order_metadata", {})
                riverrOrderId = metadata.get("riverrOrderId")
                shipped = order.get('is_shipped')
                if riverrOrderId:
                    if shipped: return shipNotification(riverrOrderId)
                    continue
                orderItems = getOrderItems(
                    storeId=shop.platformShopId,
                    apiKey=shop.apiKey,
                    orderId=platformOrderId
                )
                convertedOrderItems = []
                for item in orderItems:
                    platformProductId = item.get("id")
                    # inventoryItem = getInventoryItem(
                    #     storeId=shop.platformShopId,
                    #     apiKey=shop.apiKey,
                    #     inventoryId=item.get('code')
                    # )
                    product = Product(
                        uid=shop.uid,
                        enterpriseId=shop.enterpriseId,
                        platformProductId=platformProductId,
                        platformId="12",
                        shopId=shopId,
                        name=item.get('name'),
                        description="",
                        createdAt=datetime.now(),
                        updatedAt=datetime.now(),
                        price=item.get('price'),
                        tags=[],
                        images=[Image(url=item.get("metadata").get("image"))],
                    )
                    variant = Variant(
                        id=platformProductId,
                        price=item.get('price'),
                        sku=item.get('code').replace("/", "-", -1),
                        properties=[
                        Property(
                            name = key,
                            value =value
                        ) for key,value in (item.get("variation_list").items() if type(item.get("variation_list")) == dict else {})
                        ]
                    )
                    productId = product.save(variants=[variant])
                    orderItem = OrderItem(
                        uid=shop.uid,
                        enterpriseId=shop.enterpriseId,
                        platformId=shop.platformId,
                        platformProductId= platformProductId,
                        platformOrderItemId=item.get('id'),
                        platformOrderId = platformOrderId,
                        quantity = item.get('quantity'),
                        price = item.get('price'),
                        discount = 0,
                        tax=0,
                        subtotal= item.get('price'),
                        total=item.get('price'),
                        variantId= platformProductId,
                        name=item.get('name'),
                        shopId=shopId, 
                        createdAt= datetime.fromtimestamp(item.get("created_timestamp", datetime.now().timestamp())),
                        updatedAt= datetime.fromtimestamp(item.get('created_timestamp',  datetime.now().timestamp())),
                        productId=productId,
                        image=Image(url=item.get("metadata").get("image")), 
                        images=[Image(url=item.get("metadata").get("image"))],
                    )
                    convertedOrderItems.append(orderItem)
                shippingAddress = order.get("shipping")
                convertedOrder = Order(
                    uid=shop.uid,
                    platformId=shop.platformId,
                    shopId=shopId,
                    enterpriseId=shop.enterpriseId,
                    cancelled=False,
                    draft=False,
                    shippingAddress=Address(
                        name=f"{shippingAddress.get('first_name')} {shippingAddress.get('last_name')}",
                        address1= shippingAddress.get('address1'),
                        address2= shippingAddress.get('address2'),
                        city = shippingAddress.get('city'),
                        state = shippingAddress.get('state'),
                        zip = shippingAddress.get('postal_code'),
                        country = shippingAddress.get('country'),
                        countryCode= shippingAddress.get('country'),
                    ),
                    platformOrderId=platformOrderId, 
                    createdAt = datetime.strptime(order.get("date_added"), "%Y-%m-%d %H:%M:%S"),
                    updatedAt=datetime.strptime(order.get("date_updated"), "%Y-%m-%d %H:%M:%S"),
                    grandTotal= order.get('order_total'),
                    shipped= order.get('is_shipped'),
                    shippingCost= order.get('shipping_total'),
                    totalDiscount= order.get('discount_total'),
                    totalTax= order.get('tax_total'),
                    totalPrice= order.get('product_total'),
                    shopName=shop.name,
            )
                updates.append(dict(id=convertedOrder.save(convertedOrderItems, True, True)))
        return updates


def getOrders(storeId, apiKey, lastUpdated):
    url = "https://app.orderdesk.me/api/v2/orders"
    limit = 500
    order_by = "date_updated"
    modified_start_date = datetime.fromtimestamp(lastUpdated).strftime("%Y-%m-%d %H:%M:%S")
    modified_end_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    headers = {
        "ORDERDESK-STORE-ID": storeId,
        "ORDERDESK-API-KEY": apiKey,
        "Content-Type": "application/json"
    }
    res = requests.get(url,params=dict(
        limit=limit,
        order_by=order_by,
        modified_start_date=modified_start_date,
        modified_end_date=modified_end_date
    ), headers=headers)
    if res.status_code == 200: return res.json().get("orders")
    print(res.text, res.status_code)
    return []


def sendBatchToOrderdesk(params: Params):
    batchId = params.args.get("batchId")
    app = db.collection("appsCredentials").document('12'+params.currentUser.enterpriseId).get().to_dict()
    batch  = db.document(f"enterprises/{params.currentUser.enterpriseId}/batches/{batchId}").get()
    sentOrders = []
    if batch.exists:
        orderIds = batch.to_dict().get("orderIds", [])
        paymentStatus = batch.to_dict().get("paymentStatus")
        if paymentStatus is None: paymentStatus = "pending"
        for orderId in orderIds:
            orderInvoice = db.collection("orderInvoices").document(orderId).get()
            sentOrder = createOrder(app, orderId, paymentStatus=paymentStatus, orderInvoice=orderInvoice.to_dict())
            sentOrders.append(sentOrder)
        return sentOrders
    
    #curl "https://app.orderdesk.me/api/v2/orders/736745/order-items"
#   -H "ORDERDESK-STORE-ID: storeid"
#   -H "ORDERDESK-API-KEY: apikey"
#   -H "Content-Type: application/json"

def getOrderItems(storeId, apiKey, orderId):
    url = f"https://app.orderdesk.me/api/v2/orders/{orderId}/order-items"
    res = requests.get(url,
        headers={
         "ORDERDESK-STORE-ID": storeId,
         "ORDERDESK-API-KEY":apiKey,
         "Content-Type": "application/json"
    })
    if res.status_code == 200: return res.json().get("order_items")
    raise API_Error(res.text, res.status_code)


def getInventoryItem(storeId, apiKey, inventoryId):
    url = f"https://app.orderdesk.me/api/v2/inventory-items/{inventoryId}"
    res = requests.get(url,
        headers={
         "ORDERDESK-STORE-ID": storeId,
         "ORDERDESK-API-KEY":apiKey,
         "Content-Type": "application/json"
    })
    if res.status_code == 200: return res.json().get("inventory_item")
    raise API_Error(res.text, res.status_code)
     

def createOrder(app: dict, orderId:str, paymentStatus:bool="pending" , orderInvoice:dict=None):
    order = Order.get(orderId)
    order.shippingAddress = Address.from_dict(order.shippingAddress)
    shipping =  {
    "first_name": order.shippingAddress.name.split(" ")[0],
    "last_name": order.shippingAddress.name.split(" ")[1] if len(order.shippingAddress.name.split(" ")) > 1 else "",
    "company": order.shippingAddress.company if order.shippingAddress.company else order.shippingAddress.name,
    "address1": order.shippingAddress.address1,
    "address2": order.shippingAddress.address2,
    "city": order.shippingAddress.city,
    "state":  order.shippingAddress.state,
    "postal_code":  order.shippingAddress.zip,
    "country":  order.shippingAddress.country,
    "phone":  order.shippingAddress.phone,
  }
    decorationTypes = getDecorationTypes()
    placementOptions = getPlacementOptions()
    uid = order.uid
    user = User.get(uid)
    sourceId = f"{user.number}-{(order.orderNumber if order.orderNumber else order.platformOrderId)}"
    order_items=  [
         {
      "name": item.name,
      "price": item.price,
      "quantity": item.quantity,
    #   "weight": 1.1,
      "code": item.variant.get("sku"),
      "variation_list": {
        "Size": next((p for p in item.variant.get("properties") if p.get("name") in ["Size", "color"]), {}).get("value"),
        "Color": next((p for p in item.variant.get("properties") if p.get("name") in ["Color", "color"]), {}).get("value"),
      },
      "metadata": {
        "decoration_type": decorationTypes.get(item.decorationType),
        "print_sku": item.variant.get("sku"),
       **{f"print_url_{placementOptions.get(image.get('placement')).get('placement')}_{placementOptions.get(image.get('placement')).get('print_side')}".lower(): image.get("url") for image in item.purchaseOrderData.get("images")},
        **{f"mockup_{placementOptions.get(image.get('placement')).get('placement')}_{placementOptions.get(image.get('placement')).get('print_side')}".lower(): image.get("url") for image in item.images}
      }
    } for item in order.getOrderItems() if not item.ignored
    ]
    url = "https://app.orderdesk.me/api/v2/orders"
    res = requests.post(url,headers={
         "ORDERDESK-STORE-ID": app.get("storeId"),
         "ORDERDESK-API-KEY":app.get('apiKey'),
         "Content-Type": "application/json"
    }, json=dict(
        source_name=order.shopName,
        source_id=sourceId,
         shipping=shipping,
         order_items=order_items,
         order_metadata={
             "riverrOrderId":orderId,
             "ship_notify_url":"https://riverr-enterprise-integrations-dot-riverr-enterprise-user.uc.r.appspot.com/v2/orderdesk/ship-notification/"+orderId,
             "store":order.shopName,
             "payment_status": paymentStatus,
             "shipping_cost": orderInvoice.get("shippingCost") if orderInvoice else order.shippingCost,
             "user_email"   : user.email,
         }
    ))
    # print(res.request.url, res.request.body, res.request.headers, res.text)
    if res.status_code not in [201, 200]:raise API_Error(res.text, res.status_code)
    if res.ok:
        order.update(
            metadata = dict(
                orderDeskId = res.json().get("order").get("id")
            )
            )
        return res.json()



def shipNotification(params: Params):
    orderId = params.id
    order = Order.get(orderId=orderId)
    orderDeskId = order.metadata.get("orderDeskId")
    app = db.collection("appsCredentials").document('12'+order.enterpriseId).get().to_dict()
    url = f"https://app.orderdesk.me/api/v2/orders/{orderDeskId}/shipments"
    res = requests.get(url,
        headers={
         "ORDERDESK-STORE-ID": app.get("storeId"),
         "ORDERDESK-API-KEY":app.get('apiKey'),
         "Content-Type": "application/json"
    })
    if res.ok:
        data = res.json()
        shipments = data.get("shipments", [])
        if shipments:
            shipment = shipments[0]
            shipment = Shipment(
                    uid=order.uid,
                    enterpriseId=order.enterpriseId,
                    orderId=orderId,
                    platformId="0",
                    platformName="Manual",
                    carrierName=shipment.get("carrier_code"),
                    carrierService=shipment.get("shipment_method"),
                    cost=shipment.get("cost"),
                    trackingCode=shipment.get("tracking_number"),
                    trackingUrl=shipment.get("tracking_url"),
                    image=shipment.get("label_image"),
                    platformShipmentId=shipment.get("id"),
                    userUid=order.uid,
                    platformOrderId=order.platformOrderId,
                    pdf=None,
                )
            shipment.save()
            order.markAsShipped(shipment)
            submitShipmentToPlatform(
                    platformId=order.platformId, 
                    shopId= order.shopId, 
                    platformOrderId=order.platformOrderId,
                    trackingCode=shipment.trackingCode,
                    carrierName= shipment.carrierName,
                    carrierService=shipment.carrierService,
                )
            return shipment
    return None


def submitShipment(shop:Shop, platformOrderId:str, trackingCode:str, carrierName:str):
    url = f"https://app.orderdesk.me/api/v2/orders/{platformOrderId}/shipments"
    storeId = shop.platformShopId
    apiKey = shop.apiKey
    res = requests.post(url,headers={
         "ORDERDESK-STORE-ID": storeId,
         "ORDERDESK-API-KEY": apiKey,
         "Content-Type": "application/json"
    }, json=dict(
       tracking_number=trackingCode,
       carrier_code=carrierName
    ))
    # print(res.request.url, res.request.body, res.request.headers, res.text)
    if res.status_code not in [201, 200]:raise API_Error(res.text, res.status_code)
    return True

def getShipment(shop:Shop, platformOrderId:str):
    url = f"https://app.orderdesk.me/api/v2/orders/{platformOrderId}/shipments"
    storeId = shop.platformShopId
    apiKey = shop.apiKey
    res = requests.get(url,headers={
         "ORDERDESK-STORE-ID": storeId,
         "ORDERDESK-API-KEY": apiKey,
         "Content-Type": "application/json"
    })
    # print(res.request.url, res.request.body, res.request.headers, res.text)
    if res.status_code not in [201, 200]:raise API_Error(res.text, res.status_code)
    return res.json()