from datetime import datetime

from configs.firebase import SERVER_TIMESTAMP, db
from functions.LastUpdated import ordersLastUpdated, saveOrdersLastUpdated
from functions.Orders import (convertOrder, convertOrderItem,
                              convertShippingAddress, saveOrder)
from functions.Products import getProductById
from functions.Shops import getShops
from functions.Square.Auth import getClient, getLocations
from functions.Square.Products import getCatalogObject, saveSquareProduct
from functions.Suppliers.BlankProducts import worker
from V2.functions.Shops.main import Shop


def updateAllOrders(data):
    shops = getShops(platformId="4", credentials= True)
    res = worker(updateShopOrders, shops)
    return str(res)

def getSquareOrders(client,location_ids,lastUpdate=None):
    result = client.orders.search_orders(
    body = {
      "location_ids": location_ids,
      "query": {
        "filter": {
          "date_time_filter": {
            "updated_at": {
              "start_at": datetime.fromtimestamp(lastUpdate.get("timestamp") - 86400*3).isoformat(),
              "end_at": datetime.now().isoformat()
            }
          }
        },
        "sort": {
          "sort_field": "UPDATED_AT",
          "sort_order": "DESC"
        }
      }
  }
)
    if result.is_success():
        print(result.body)
        return result.body.get('orders', [])
    elif result.is_error():
        print(result.errors)
        # raise API_Error(result.errors)
        return []
    

def getSquareOrder(client, orderId):
    result = client.orders.retrieve_order(
      order_id = orderId
    )

    if result.is_success():
      # print(result.body)
      return result.body.get("order")
    elif result.is_error():
      print(result.errors)

def updateSingleOrder(shop, platformOrderId):
    if shop:
      updates = []
      uid = shop.get('uid')
      shopId  = shop.get('id')
      platformId = shop.get('platformId')
      accessToken = shop.get('accessToken')
      enterpriseId = shop.get('enterpriseId')
      client = getClient(accessToken)
      orderProducts = {}
      order = getSquareOrder(client, platformOrderId)
      # print(orders)
          # customerId = order.get('customer_id')
          # customer = getCustomer(client, customerId)
      address = None
      fulfillments = order.get("fulfillments", [])
      if not fulfillments: 
          print("no fulfillments")
          return 
      shipment_details = next((a.get("shipment_details") for a in fulfillments if a.get("shipment_details", {})), None)
      if not shipment_details: 
          print("no shipment_details")
          return
      recipient = shipment_details.get("recipient")
      if not recipient:
        print("no recipient")
        return
      address = recipient.get("address")
      if not address: 
        print("no address")
        return
        # print(customer, order.get("id"))
      if address:
            # address = customer.get('address')
            # print(order.get("version"))
            convertededOrder = convertOrder(
                uid=uid,
                platformId=platformId,
                shopId= shopId,
                enterpriseId=enterpriseId,
                shippingAddress=convertShippingAddress(
                    name = address.get('first_name') + " " +address.get("last_name"), 
                    address1= address.get('address_line_1'),
                    address2= address.get('address_line_2'),
                    city= address.get('locality'),
                    state= address.get('state', ""),
                    zip= address.get('postal_code'),
                    country= address.get('country'),
                ),
                cancelled = order.get('state') == "CANCELED",
                shipped= order.get('state') == "COMPLETED",
                createdAt= SERVER_TIMESTAMP,
                updatedAt= SERVER_TIMESTAMP,
                currencyCode= order.get('total_money', {}).get('currency', "USD"),
                platformOrderId = order.get('id'),
                grandTotal = order.get('total_money', {}).get('amount')/100 if order.get('total_money', {}).get('amount') else 0,
                shippingCost= 0,
                totalDiscount= order.get('total_discount_money').get('amount')/100 if order.get('total_discount_money').get('amount') else 0,
                totalPrice = order.get('total_money', {}).get('amount')/100 if order.get('total_money', {}).get('amount') else 0,
                totalTax = order.get('total_tax_money').get('amount')/100 if order.get('total_tax_money').get('amount')!=0 else 0,
                metadata=dict(
                    version=order.get("version")
                )
            )
            items = order.get('line_items', [])
            for item in items:
              variantId = item.get('catalog_object_id')
              productData =  orderProducts.get(variantId)
              # if not (productData):
              #   product, variant = findVariantProduct(variantId)
              #   orderProducts[variantId] = (product, variant)
              # else:
              product, variant = None,None
              if not (product or variant):
                response  = getCatalogObject(client, variantId)
                # print("response", response)
                product, variants = saveSquareProduct(response, shop, client)
                variant = next((v for v in variants if v.get("id") == variantId), None)
              # print(product, variant)
              convertedOrderItems = []
              convertedOrderItem = convertOrderItem(
                      uid = uid,
                      platformId = platformId,
                      enterpriseId=enterpriseId,
                      platformOrderItemId= item.get('uid'),
                      platformOrderId = order.get('id'),
                      shopId=shopId,
                      cancelled= order.get('state') == "CANCELED",
                      createdAt= SERVER_TIMESTAMP,
                      updatedAt= SERVER_TIMESTAMP,
                      platformProductId= product.get('platformProductId'),
                      quantity= int(item.get('quantity')),
                      shipped= item.get('fulfillment_status') == 'fulfilled',
                      price=item.get('base_price_money').get('amount')/100 if item.get('base_price_money').get('amount') else variant.get('price',0),
                      variantId=variantId,
                      variant=variant,
                      product=product,
                      name=product.get('name'),
                      image=product.get("images")[0] if product.get("images") else {},
                  )
              convertedOrderItems.append(convertedOrderItem)
              # print(convertededOrder, convertedOrderItems)
              return saveOrder(convertededOrder, convertedOrderItems, True, True)
    

def updateShopOrders(shop):
    if shop:
      updates = []
      uid = shop.get('uid')
      shopId  = shop.get('id')
      platformId = shop.get('platformId')
      accessToken = shop.get('accessToken')
      enterpriseId = shop.get('enterpriseId')
      client = getClient(accessToken)
      locations = getLocations(client)
      lastUpdate = ordersLastUpdated(shopId)
      orderProducts = {}
      orders = getSquareOrders(client, [location.get('id')for location in locations], lastUpdate)
      # print(orders)
      for order in orders:
          # customerId = order.get('customer_id')
          # customer = getCustomer(client, customerId)
          address = None
          fulfillments = order.get("fulfillments", [])
          if not fulfillments: 
              print("no fulfillments")
              continue
          shipment_details = next((a.get("shipment_details") for a in fulfillments if a.get("shipment_details", {})), None)
          if not shipment_details: 
              print("no shipment_details")
              continue
          recipient = shipment_details.get("recipient")
          if not recipient:
            print("no recipient")
            continue
          address = recipient.get("address")
          if not address: 
            print("no address")
            continue
          # print(customer, order.get("id"))
          if address:
              # address = customer.get('address')
              # print(order.get("version"))
              convertededOrder = convertOrder(
                  uid=uid,
                  platformId=platformId,
                  shopId= shopId,
                  enterpriseId=enterpriseId,
                  shippingAddress=convertShippingAddress(
                      name = address.get('first_name') + " " +address.get("last_name"), 
                      address1= address.get('address_line_1'),
                      address2= address.get('address_line_2'),
                      city= address.get('locality'),
                      state= address.get('state', ""),
                      zip= address.get('postal_code'),
                      country= address.get('country'),
                  ),
                  cancelled = order.get('state') == "CANCELED",
                  shipped= order.get('state') == "COMPLETED",
                  createdAt= SERVER_TIMESTAMP,
                  updatedAt= SERVER_TIMESTAMP,
                  currencyCode= order.get('total_money', {}).get('currency', "USD"),
                  platformOrderId = order.get('id'),
                  grandTotal = order.get('total_money', {}).get('amount')/100 if order.get('total_money', {}).get('amount') else 0,
                  shippingCost= 0,
                  totalDiscount= order.get('total_discount_money').get('amount')/100 if order.get('total_discount_money').get('amount') else 0,
                  totalPrice = order.get('total_money', {}).get('amount')/100 if order.get('total_money', {}).get('amount') else 0,
                  totalTax = order.get('total_tax_money').get('amount')/100 if order.get('total_tax_money').get('amount')!=0 else 0,
                  metadata=dict(
                     version=order.get("version")
                  )
              )
              items = order.get('line_items', [])
              for item in items:
                variantId = item.get('catalog_object_id')
                productData =  orderProducts.get(variantId)
                # if not (productData):
                #   product, variant = findVariantProduct(variantId)
                #   orderProducts[variantId] = (product, variant)
                # else:
                product, variant = None,None
                if not (product or variant):
                  response  = getCatalogObject(client, variantId)
                  # print("response", response)
                  product, variants = saveSquareProduct(response, shop, client)
                  variant = next((v for v in variants if v.get("id") == variantId), None)
                # print(product, variant)
                convertedOrderItems = []
                convertedOrderItem = convertOrderItem(
                        uid = uid,
                        platformId = platformId,
                        enterpriseId=enterpriseId,
                        platformOrderItemId= item.get('uid'),
                        platformOrderId = order.get('id'),
                        shopId=shopId,
                        cancelled= order.get('state') == "CANCELED",
                        createdAt= SERVER_TIMESTAMP,
                        updatedAt= SERVER_TIMESTAMP,
                        platformProductId= product.get('platformProductId'),
                        quantity= int(item.get('quantity')),
                        shipped= item.get('fulfillment_status') == 'fulfilled',
                        price=item.get('base_price_money').get('amount')/100 if item.get('base_price_money').get('amount') else variant.get('price',0),
                        variantId=variantId,
                        variant=variant,
                        product=product,
                        name=product.get('name'),
                        image=product.get("images")[0] if product.get("images") else {},
                    )
                convertedOrderItems.append(convertedOrderItem)
                # print(convertededOrder, convertedOrderItems)
              updates.append(saveOrder(convertededOrder, convertedOrderItems, True, True))
      saveOrdersLastUpdated(shopId = shopId, count= len(updates))
    return f"Orders updated => {len(updates)}" 
    
def getCustomer(client, customerId):
    result = client.customers.retrieve_customer(customer_id=customerId)
    if result.is_success():
        return result.body.get("customer")
    print(result.errors)
    return {}

def findVariantProduct(variantId):
  result = db.collection_group("variants").where("id", "==", variantId).get()
  if result:
    variant =  result[0].to_dict()
    product = getProductById(variant.get('productId'))
    return product, variant
  return None, None


def submitShipment(shop:Shop, platformOrderId, carrierName, trackingCode, version):
  client = getClient(shop.accessToken)
  result =  client.orders.retrieve_order(
    order_id = platformOrderId
  )
  if result.is_success():
    # print(result.body)
    version = result.body.get("order", {}).get("version")
  elif result.is_error():
    print(result.errors)
  # print(version)
  result = client.orders.update_order(
      order_id = platformOrderId,
      body = {
        "order": {
          "fulfillments": [
            {
              "type": "SHIPMENT",
              "shipment_details": {
                "tracking_number": trackingCode,
                "carrier": carrierName,
                # "recipient": {
                #    "display_name": "Taylor Miller"
                # }
              },
              # "line_item_application": "ALL"
            }
      ],
       "idempotency_key": str(int(datetime.now().timestamp())),
        "version": version
      },
    }
  )
  if result.is_success(): print(result.body)
  elif result.is_error(): print(result.errors)


# submitShipment(Shop.get("QfhtkrcUPorngEbYjhUP"), "YUk9M0ffQuQdboJcu2fSKiLeI27YY", "USPS", "9400136110368253352866", 9)