from configs.firebase import db
from functions.Bins import clearBin
from functions.Orders import getOrder, orderMarkShipped
from functions.Shipments import Convert, EasyPost, Machship, Shipstation
from functions.Shopify.Fulfillment import submitShopifyShipment
from functions.WooCommerce.Orders import submitWooShipment
from V2.functions.Etsy.Orders import submitShipment as submitEtsyShipment
from V2.functions.Orders.main import Order
from V2.functions.Shipments.main import Shipment
from V2.functions.Shops.main import Shop


def createShipment(params):
    user = params.get("currentUser")
    enterpriseId, uid = user.get("enterpriseId"), user.get("uid")
    rate = params.get("rate")
    orderId = params.get("orderId")
    fromAddressId = params.get("fromAddressId")
    fromAddress = Convert.getAddress(fromAddressId)
    order = getOrder(orderId)
    insurance = params.get("insurance", False)
    shipment = {}
    if rate.get("platformId") == "EASYPOST":
        shipment = EasyPost.createShipment(
            uid=uid, order=order, rate=rate, insurance=insurance
        )
    elif rate.get("platformId") == "SHIPSTATION":
        parcelId = params.get("parcelId")
        parcel = Convert.getParcel(parcelId)
        if not parcel:
            parcel = dict(
                height=params.get("height", 2),
                weight=params.get("weight", 5),
                length=params.get("length", 12),
                width=params.get("width", 15),
            )
        parcel["weight"] = params.get("weight", 5)
        fromAddress = Convert.getAddress(fromAddressId)
        if order.get("shopName") and enterpriseId != "60D7GFDlMFFd6IsK1e58":
            fromAddress["name"] = order.get("shopName")
        shipment = Shipstation.createShipment(
            uid=uid,
            order=order,
            enterpriseId=enterpriseId,
            fromAddress=fromAddress,
            rate=rate,
            parcel=parcel,
            packageCode=params.get("packageCode"),
        )
    if rate.get("platformId") == "MACHSHIP":
        shipment = Machship.createShipment(
            uid=uid,
            order=order,
            enterpriseId=enterpriseId,
            fromAddress=fromAddress,
            rate=rate,
            parcel=params.get("parcel"),
        )
    order = Order.from_dict(order)
    shipment = Shipment.from_dict(shipment)
    order.markAsShipped(shipment)
    clearBin(enterpriseId, orderId)
    submitShipmentToPlatform(
        order.platformId,
        order.shopId,
        order.platformOrderId,
        shipment.trackingCode,
        shipment.carrierName,
        serviceName=shipment.carrierService,
        trackingUrl=shipment.trackingUrl,
        order=order.to_dict(),
    )
    return dict(shipment=shipment.to_dict())


def getCarriers(params):
    user = params.get("currentUser")
    enterpriseId = user.get("enterpriseId")
    carriers = EasyPost.getCarriers(enterpriseId)
    carriers.extend(Shipstation.getCarriers(enterpriseId))
    carriers.extend(Machship.getCarriers(enterpriseId))
    if enterpriseId == "60D7GFDlMFFd6IsK1e58":
        order = getOrder(params.get("orderId"))
        shipping = order.get("metadata", {}).get("shipping", {})
        carriers = [
            carrier
            for carrier in carriers
            if carrier.get("description") == shipping.get("carrier")
        ]
    return dict(carriers=carriers)


def getRates(params):
    user = params.get("currentUser")
    enterpriseId = user.get("enterpriseId")
    fromAddressId = params.get("fromAddressId")
    carrierId = params.get("carrierId")
    platformId = params.get("platformId", "EASYPOST")
    orderId = params.get("orderId")
    packageCode = params.get("packageCode")
    parcelId = params.get("parcelId")
    parcel = Convert.getParcel(parcelId)
    if not fromAddressId:
        userId = user.get("uid")
        user = db.collection("users").document(userId).get()
        enterpriseId = user.get("enterpriseId")
        enterprise = db.collection("enterprises").document(enterpriseId).get()
        adminUserId = enterprise.get("uid")
        query = (
            db.collection("addresses")
            .where("uid", "==", adminUserId)
            .where("default", "==", True)
        )
        address = query.limit(1).get()
        if address:
            first_address = address[0].to_dict()
            fromAddressId = first_address.get("id")
    if not parcel:
        parcel = dict(
            height=params.get("height", 2),
            weight=params.get("weight", 5),
            length=params.get("length", 12),
            width=params.get("width", 15),
        )
    parcel["weight"] = (
        grams2Ounc(params.get("weight", 5))
        if enterpriseId == "3vRxw0HKksLTyVzsN83d"
        else params.get("weight", 5)
    )
    order = getOrder(orderId)
    fromAddress = Convert.getAddress(fromAddressId)
    if order.get("shopName") and enterpriseId != "60D7GFDlMFFd6IsK1e58":
        fromAddress["name"] = order.get("shopName")
    rates = []
    if platformId == "EASYPOST":
        rates = EasyPost.getRates(enterpriseId, fromAddress, order, parcel, carrierId)
    elif platformId == "SHIPSTATION":
        rates.extend(
            Shipstation.getRates(
                enterpriseId, fromAddress, order, parcel, carrierId, packageCode
            )
        )
    elif platformId == "MACHSHIP":
        rates.extend(
            Machship.getRates(
                enterpriseId, fromAddress, order, parcel, carrierId, packageCode
            )
        )
    # else:
    #     raise API_Error('Platform not found.', 404)
    if enterpriseId == "60D7GFDlMFFd6IsK1e58":
        shipping = order.get("metadata", {}).get("shipping", {})
        carrierId, serviceId = shipping.get("carrier"), shipping.get("priority")
        rates = [
            rate
            for rate in rates
            if rate.get("carrierName") == carrierId
            and rate.get("serviceId") == serviceId
        ]
    return dict(rates=rates)


def grams2Ounc(grams):
    return round(float(grams) / 28.35, 2)


def submitShipmentToPlatform(
    platformId,
    shopId,
    platformOrderId,
    trackingCode,
    carrierName,
    carrierService=None,
    **kwargs
):
    if platformId == "0":
        return
    shop = Shop.get(shopId, True)
    order = kwargs.get("order")
    if platformId == "1":
        submitEtsyShipment(shop, platformOrderId, trackingCode, carrierName)
    elif platformId == "2":
        submitShopifyShipment(shop, platformOrderId, carrierName, trackingCode)
    elif platformId == "3":
        submitWooShipment(shop, platformOrderId, carrierName, trackingCode)
    elif platformId == "5":
        from functions.Shipstation.Orders import \
            submitShipment as submitShipstationShipment

        submitShipstationShipment(shop, platformOrderId, carrierName, trackingCode)
    elif platformId == "10":
        from V2.functions.Squarespace.Orders import \
            submitShipment as submitSquarespaceShipment

        submitSquarespaceShipment(
            shop,
            platformOrderId=platformOrderId,
            carrierName=carrierName,
            trackingCode=trackingCode,
            carrierService=carrierService,
            **kwargs
        )
    elif platformId == "4":
        from functions.Square.Orders import \
            submitShipment as submitSquareShipment

        submitSquareShipment(
            shop,
            platformOrderId=platformOrderId,
            carrierName=carrierName,
            trackingCode=trackingCode,
            version=order.get("metadata", {}).get("version"),
        )
    elif platformId == "12":
        from V2.functions.Orderdesk.Orders import \
            submitShipment as submitOrderdeskShipment

        submitOrderdeskShipment(
            shop,
            platformOrderId=platformOrderId,
            carrierName=carrierName,
            trackingCode=trackingCode,
        )

    else:
        print("Platform not found.")


def submitOrderShipment(params):
    orderId = params.get("orderId")
    trackingCode = params.get("trackingCode")
    carrierName = params.get("carrierName")
    order = Order.get(orderId)
    submitShipmentToPlatform(
        order.platformId,
        order.shopId,
        order.platformOrderId,
        trackingCode,
        carrierName,
        order=order.to_dict(),
    )
    return dict(order=order)
