import base64
import json
import os
from datetime import date

import requests
from requests.auth import HTTPBasicAuth

from configs.firebase import SANDBOX
from functions.Etsy.Orders import getCountriesFromDb
from functions.Response import API_Error
from functions.Shipments.Convert import (convertCarrier, convertRate,
                                         getShipmentPlatformCreds,
                                         saveShipment)
from functions.Storage import get_file_path, upload_blob


def getCarriers(enterpriseId:str):
    creds = getShipmentPlatformCreds(enterpriseId, "SHIPSTATION")
    carriers:list[dict] = []
    if creds:
        if creds.get("enabled") == False: return carriers
        try:
            res = requests.get('https://ssapi.shipstation.com/carriers', auth = HTTPBasicAuth(creds.get('apiKey'), creds.get('apiSecret')))
            if res.status_code == 200:
                carriers = res.json()
                carriers = [convertCarrier(id=carrier.get('code'), platformId="SHIPSTATION",platformName = "ShipStation", name=carrier.get('name'), description= carrier.get('nickname')) for carrier in carriers]
            else:print(res.text, res.status_code)
        except Exception as e:
            print(e)
    return carriers

def getServices(enterpriseId:str, carrierId:str):
    creds = getShipmentPlatformCreds(enterpriseId, "SHIPSTATION")
    services:list[dict] = []
    if creds:
        try:
            res = requests.get(f'https://ssapi.shipstation.com/carriers/listservices?carrierCode={carrierId}', auth = HTTPBasicAuth(creds.get('apiKey'), creds.get('apiSecret')))
            if res.status_code == 200:
                services = res.json()
                print(services)
            else:print(res.text)
        except Exception as e:
            print(e)
    return services

def getRates(enterpriseId:str, fromAddress:dict, order:dict, parcel:dict, carrierId:str, packageCode:str = None):
    creds = getShipmentPlatformCreds(enterpriseId, "SHIPSTATION")
    rates = []
    if creds:
            toCountry, toZip = order.get('shippingAddress').get('country'),order.get('shippingAddress').get('zip')
            if toCountry in ["United States", "United States of America"]:
                toCountry = "US"
            elif len(toCountry) != 2: 
                countries = [c.get("code") for c in getCountriesFromDb().values() if c.get('name') == toCountry]
                if countries: toCountry = countries[0]
            dimensions = dict(
            length=parcel.get('length'),
            width=parcel.get('width'),
            height=parcel.get('height'),
            units="inches"
        )
            if packageCode == "letter":
                dimensions = dict(
                    length=4,
                    width=6,
                    height=0.025,
                    units="inches"
                )
            res = requests.post('https://ssapi.shipstation.com/shipments/getrates', auth = HTTPBasicAuth(creds.get('apiKey'), creds.get('apiSecret')),
                 json=dict(
                    carrierCode=carrierId,
                    fromPostalCode=fromAddress.get('zip'),
                    toCountry=toCountry, 
                    toPostalCode=toZip, 
                    weight=dict(
                        value=float(parcel.get('weight')),
                        units=parcel.get("weightUnit", "ounces")
                    ),
                    dimensions=dimensions,
                    packageCode=packageCode
                    ))
            if res.status_code == 200:
                rates = res.json()
                rates = [convertRate(
                    id = rate.get('serviceCode'),
                    carrierId=carrierId,
                    carrierName=rate.get('serviceName'),
                    currency="USD",
                    cost= rate.get('shipmentCost'), 
                    name= rate.get('serviceName'),
                    platformId = "SHIPSTATION",
                    platformName = "ShipStation",
                    serviceId=rate.get("serviceCode")
                ) for rate in rates]
            else: 
                print(res.request.body,res.status_code,res.text)
                raise API_Error(res.json().get('ExceptionMessage'), res.status_code)
    return rates
            

def createShipment(uid:str,order:dict,  enterpriseId, fromAddress:dict, rate:dict, parcel:dict, packageCode=None):
    creds = getShipmentPlatformCreds(enterpriseId, "SHIPSTATION")
    toAddress = order.get('shippingAddress', {})
    toCountry = str(toAddress.get('country')).lower()
    if toCountry in {"united states", "us", "united states of america"}:
        toAddress['country'] = "US"
    else:
        countries = getCountriesFromDb().values()
        toAddress['country'] = next(
            (c.get("code") for c in countries if str(c.get('name')).lower() == toCountry), 
            "US"
        )   
    fromAddress  = dict(
                name=fromAddress.get('shopName') if fromAddress.get('shopName') else fromAddress.get('name'),
                street1 = fromAddress.get('address1'),
                street2 = fromAddress.get('address2'),
                city = fromAddress.get('city'),
                state = fromAddress.get('state'),
                postalCode = fromAddress.get('zip'),
                country = fromAddress.get('countryCode') if fromAddress.get('countryCode') else fromAddress.get('country'),
                phone = fromAddress.get('phone'),
                company = fromAddress.get('shopName') if fromAddress.get('shopName') else fromAddress.get('company', fromAddress.get("name")),
            )
    toAddress  = dict(
        name=toAddress.get('name'),
        street1 = toAddress.get('address1'),
        street2 = toAddress.get('address2'),
        city = toAddress.get('city'),
        state = toAddress.get('state'),
        postalCode = toAddress.get('zip'),
        country = toAddress.get('country'),
        phone = toAddress.get('phone'),
        company = fromAddress.get('company')
    )
    dimensions = dict(
            length=parcel.get('length'),
            width=parcel.get('width'),
            height=parcel.get('height'),
            units="inches"
        )
    if packageCode == "letter":
        dimensions = dict(
            length=4,
            width=6,
            height=0.025,
            units="inches"
        )
    res = requests.post(
        'https://ssapi.shipstation.com/shipments/createlabel', 
        auth = HTTPBasicAuth(creds.get('apiKey'), creds.get('apiSecret')),
        headers={"Content-Type": "application/json"},
        data=json.dumps(dict(
        carrierCode=rate.get('carrierId'),
        weight=dict(
            value=parcel.get('weight'),
            units="grams" if enterpriseId == "3vRxw0HKksLTyVzsN83d" else "ounces" 
        ),
        dimensions=dimensions,
        serviceCode = rate.get('id'),
        packageCode=packageCode,
        shipDate=date.today().isoformat(),
        shipFrom=fromAddress,
        shipTo=toAddress,
        testLabel=SANDBOX or uid == "zNAlxdaZG6hKf6vexv6ljqHyP8i1" or enterpriseId in ["gv51IUBOdmyCPcW1NfDz"],
        internationalOptions = dict(
            nonDelivery="treat_as_abandoned",
            contents = "merchandise",
            customsItems= [
                dict(
                    description = "unisex printed t shirts",
                    quantity=1,
                    value=10,
                    harmonizedTariffCode=640411,
                    countryOfOrigin="US"
                )
        ]
        ) if fromAddress.get("country") != toAddress.get("country") or str(toAddress.get("state")).lower() in [
                "guam", "american samoa", "puerto rico", "us virgin islands", "northern mariana islands"
            ] else None
    )))
    if res.status_code == 200:
        shipment = res.json()
        labelData = shipment.get('labelData')
        file_path = get_file_path(f"{shipment.get('shipmentId')}.pdf")
        with open(file_path, "wb") as file:
            file.write(base64.b64decode(str(labelData)))
        label = upload_blob(
            file_path, f"users/{uid}/shipments/{shipment.get('shipmentId')}.pdf")
        os.remove(file_path)
        shipment  = saveShipment(
            uid=uid,
            enterpriseId=enterpriseId,
            platformId="SHIPSTATION",
            platformName= "ShipStation",
            orderId=order.get('id'),
            platformOrderId=order.get('platformOrderId'),
            image=None,
            platformShipmentId=shipment.get('shipmentId'),
            carrierName= shipment.get('carrierCode'),
            carrierService= shipment.get('serviceCode'),
            cost=shipment.get('shipmentCost'),
            pdf=label,
            trackingCode= shipment.get('trackingNumber'),
            userUid= order.get('uid'),
            routedOrderIds = order.get("routedOrderIds", []),
        )
        return shipment
    print(res.text)
    raise API_Error(res.text, res.status_code)