from datetime import datetime

from configs.firebase import db
from functions.Applications import getAppCredentials
from functions.LastUpdated import ordersLastUpdated, saveOrdersLastUpdated
from functions.Orders import (convertOrder, convertOrderItem,
                              convertShippingAddress, saveOrder)
from functions.Products import convertProperty, getProductVariantByPlatformId
from functions.Response import API_Error
from functions.Shops import getShopById, getShops
from functions.Suppliers.BlankProducts import worker
from requests_oauthlib import OAuth1Session


def updateAllOrders(params={}):
    shops = getShops(platformId="1", credentials= True)
    shops = [shop for shop in shops if not shop.get("apiVersion")]
    worker(updateShopOrders, shops)

def updateShopOrders(shop):
    if shop:
        try:
            shopId = shop.get('id')
            shopName = shop.get('name')
            updates = []
            uid = shop.get('uid')
            enterpriseId = shop.get('enterpriseId')
            oauthToken = shop.get("oauthToken")
            oauthTokenSecret = shop.get("oauthTokenSecret")
            appId = shop.get("appId")
            application = getAppCredentials(appId)
            lastUpdate = ordersLastUpdated(shopId)
            timestamp = lastUpdate.get("timestamp")
            toTimestamp = lastUpdate.get("toTimestamp")
            platformShopId = shop.get("platformShopId")
            platformId = shop.get("platformId")
            oauth = OAuth1Session(application.get("apiKey"), application.get("apiSecret"), oauthToken,oauthTokenSecret)
            nowTime = int(datetime.now().timestamp())
            response = oauth.get(f"https://openapi.etsy.com/v2/shops/{platformShopId}/receipts",params=dict(limit=100,max_last_modified= toTimestamp if toTimestamp else int(datetime.now().timestamp()),min_last_modified=timestamp,was_paid=True))
            shippedRes = oauth.get(f"https://openapi.etsy.com/v2/shops/{platformShopId}/receipts",params=dict(limit=100,max_last_modified=toTimestamp if toTimestamp else int(datetime.now().timestamp()),min_last_modified=timestamp,was_paid=True, was_shipped=True))
            orders = []
            if shippedRes.status_code == 200:
                orders.extend(shippedRes.json().get('results', []))
                print(f"{shopId} Shipped Orders: {len(orders)}")
            if response.status_code ==  200:
                jsonres = response.json()
                print(f"{shopId} Orders: {len(jsonres.get('results', []))}")
                orders.extend(jsonres.get("results", []))
                countries = getCountries(application.get("apiKey"),application.get("apiSecret"),oauthToken,oauthTokenSecret)
                for order in orders:
                    id = order.get('receipt_id')
                    itemsRes = oauth.get(f"https://openapi.etsy.com/v2/receipts/{id}/transactions")
                    items = []
                    if itemsRes.status_code == 200:
                        items = itemsRes.json().get("results", [])
                    else:
                        print(itemsRes.text)
                        raise API_Error(itemsRes.text, itemsRes.status_code)
                    orderItems = []
                    for item in items:
                        variantId = str(item.get('product_data').get('product_id'))
                        variant = getProductVariantByPlatformId(str(item.get('listing_id')),variantId)
                        if not variant: variant = {}
                        variations = item.get('variations', [])
                        variant['properties'] =  [convertProperty(
                                name = variation.get('formatted_name'),
                                id = variation.get('property_id'),
                                value = variation.get('formatted_value')
                            ) for variation in variations]
                        orderItem = convertOrderItem(
                            uid=uid,
                            enterpriseId=enterpriseId,
                            platformId=platformId,
                            platformProductId= item.get('listing_id'),
                            platformOrderItemId=item.get('transaction_id'),
                            platformOrderId = id,
                            quantity = item.get('quantity'),
                            price = item.get('price'),
                            variantId= variantId,
                            name = item.get('title'),
                            shopId=shopId, 
                            createdAt= datetime.fromtimestamp(item.get("creation_tsz")),
                            updatedAt= datetime.fromtimestamp(item.get('creation_tsz')),
                            variant= variant,
                        )
                        orderItems.append(orderItem)
                    country = countries.get(str(order.get('country_id')), {})
                    convertedOrder = convertOrder(
                        uid = uid,
                        platformId = platformId,
                        shopId = shopId,
                        enterpriseId= enterpriseId,
                        shippingAddress=convertShippingAddress(
                            name=order.get('name'),
                            address1= order.get('first_line'),
                            address2= order.get('second_line'),
                            city = order.get('city'),
                            state = order.get('state'),
                            zip = order.get('zip'),
                            country = country.get('name'),
                            countryCode= country.get('code'),
                            email=order.get('buyer_email'),
                        ),
                        platformOrderId= id, 
                        createdAt = datetime.fromtimestamp(order.get('creation_tsz')),
                        updatedAt= datetime.fromtimestamp(order.get('last_modified_tsz')),
                        grandTotal= order.get('grandtotal'),
                        shipped= order.get('was_shipped'),
                        currencyCode= order.get('currency_code'),
                        shippingCost= order.get('total_shipping_cost'),
                        totalDiscount= order.get('discount_amt'),
                        totalTax= order.get('total_tax_cost'),
                        totalPrice= order.get('total_price'),
                        shopName=shopName,
                    )
                    updates.append(saveOrder(convertedOrder, orderItems))
                saveOrdersLastUpdated(
                    shopId = shopId,
                    count=len(updates),
                    timestamp= nowTime
                    )
                return f"Orders Updated => {len(updates)}"
            else: 
                print(response.text)
                return response.text
        except: return "No updates"
    return "No Updates"

def getCountries(apiKey, apiSecret, token, secret):
    results = getCountriesFromDb()
    if results: return results
    oauth = OAuth1Session(apiKey, apiSecret, token, secret)
    res = oauth.get(f"https://openapi.etsy.com/v2/countries")
    if res.status_code == 200:
        results =  res.json().get('results', [])
        results = {str(result.get('country_id')): dict(name=result.get('name'),code=result.get("iso_country_code")) for result in results}
        saveCountries(results)
        return results
    print(res.text, res.status_code)
    return {}

def saveCountries(countries={}):
    db.collection("platforms").document("1").collection("settings").document("countries").set(countries)
    return None

def getCountriesFromDb():
    return db.collection("platforms").document("1").collection("settings").document("countries").get().to_dict()

def submitShipment(shop, platformOrderId, trackingCode, carrierName):
    shopId = shop.get('id')
    oauthToken = shop.get('oauthToken')
    oauthTokenSecret = shop.get('oauthTokenSecret')
    appId = shop.get('appId')
    app = getAppCredentials(appId)
    key = app.get('apiKey')
    secret = app.get('apiSecret')
    oauth= OAuth1Session(key, secret, oauthToken, oauthTokenSecret)
    res = oauth.post(f"https://openapi.etsy.com/v2/shops/{shop.get('platformShopId')}/receipts/{platformOrderId}/tracking", params=dict(carrier_name=carrierName, tracking_code=trackingCode, send_bcc=True))
    if res.status_code in (200, 201):
        print("Shipment submitted.", shopId, platformOrderId, trackingCode, carrierName)
        return res.json()
    print(res.text, res.status_code)
    raise API_Error(res.text, res.status_code, dict(shopId=shopId, platformOrderId=platformOrderId, trackingCode=trackingCode, carrierName=carrierName))



def updateSingleOrder(params:dict):
    try:
            shopId = params.get("shopId")
            shop = getShopById(shopId, True)
            if not shop: return
            platformOrderId = str(params.get("id"))
            shopName = shop.get('name')
            uid = shop.get('uid')
            enterpriseId = shop.get('enterpriseId')
            oauthToken = shop.get("oauthToken")
            oauthTokenSecret = shop.get("oauthTokenSecret")
            appId = shop.get("appId")
            application = getAppCredentials(appId)
            lastUpdate = ordersLastUpdated(shopId)
            timestamp = lastUpdate.get("timestamp")
            toTimestamp = lastUpdate.get("toTimestamp")
            platformId = shop.get("platformId")
            oauth = OAuth1Session(application.get("apiKey"), application.get("apiSecret"), oauthToken,oauthTokenSecret)
            response = oauth.get(f"https://openapi.etsy.com/v2/receipts/{platformOrderId}",params=dict(limit=100,max_last_modified= toTimestamp if toTimestamp else int(datetime.now().timestamp()),min_last_modified=timestamp,was_paid=True))
            orders = []
            if response.status_code ==  200:
                jsonres = response.json()
                orders.extend(jsonres.get("results", []))
                countries = getCountries(application.get("apiKey"),application.get("apiSecret"),oauthToken,oauthTokenSecret)
                for order in orders:
                    itemsRes = oauth.get(f"https://openapi.etsy.com/v2/receipts/{platformOrderId}/transactions")
                    items = []
                    if itemsRes.status_code == 200:
                        items = itemsRes.json().get("results", [])
                    else:
                        print(itemsRes.text)
                        raise API_Error(itemsRes.text, itemsRes.status_code)
                    orderItems = []
                    for item in items:
                        variantId = str(item.get('product_data').get('product_id'))
                        variant = getProductVariantByPlatformId(str(item.get('listing_id')),variantId)
                        if not variant: variant = {}
                        variations = item.get('variations', [])
                        variant['properties'] =  [convertProperty(
                                name = variation.get('formatted_name'),
                                id = variation.get('property_id'),
                                value = variation.get('formatted_value')
                            ) for variation in variations]
                        orderItem = convertOrderItem(
                            uid=uid,
                            enterpriseId=enterpriseId,
                            platformId=platformId,
                            platformProductId= item.get('listing_id'),
                            platformOrderItemId=item.get('transaction_id'),
                            platformOrderId = platformOrderId,
                            quantity = item.get('quantity'),
                            price = item.get('price'),
                            variantId= variantId,
                            name = item.get('title'),
                            shopId=shopId, 
                            createdAt= datetime.fromtimestamp(item.get("creation_tsz")),
                            updatedAt= datetime.fromtimestamp(item.get('creation_tsz')),
                            variant= variant,
                        )
                        orderItems.append(orderItem)
                    country = countries.get(str(order.get('country_id')), {})
                    convertedOrder = convertOrder(
                        uid = uid,
                        platformId = platformId,
                        shopId = shopId,
                        enterpriseId= enterpriseId,
                        shippingAddress=convertShippingAddress(
                            name=order.get('name'),
                            address1= order.get('first_line'),
                            address2= order.get('second_line'),
                            city = order.get('city'),
                            state = order.get('state'),
                            zip = order.get('zip'),
                            country = country.get('name'),
                            countryCode= country.get('code'),
                            email=order.get('buyer_email'),
                        ),
                        platformOrderId= platformOrderId, 
                        createdAt = datetime.fromtimestamp(order.get('creation_tsz')),
                        updatedAt= datetime.fromtimestamp(order.get('last_modified_tsz')),
                        grandTotal= order.get('grandtotal'),
                        shipped= order.get('was_shipped'),
                        currencyCode= order.get('currency_code'),
                        shippingCost= order.get('total_shipping_cost'),
                        totalDiscount= order.get('discount_amt'),
                        totalTax= order.get('total_tax_cost'),
                        totalPrice= order.get('total_price'),
                        shopName=shopName,
                    )
                    return saveOrder(convertedOrder, orderItems,  True)
            else: 
                print(response.text)
                return response.text
    except Exception as e: 
        print(e)
        return "No updates"
