from datetime import datetime
from typing import List

import requests

from configs.env import PROJECT_ID
from configs.firebase import db
from functions.Response import API_Error
from functions.Shopify.Auth import apiVersion, createHeader
from V2.functions.Products.main import Product
from V2.functions.Products.Variants import Variant
from V2.functions.Shopify.main import ShopifyGraphQLClient, validate_shopify_id
from V2.functions.Shopify.Products import getShopifyProductVariants
from V2.functions.Shops.main import Shop
from V2.functions.Users.main import Enterprise
from V2.Params import Params


def getShopLocations(params: Params):
    shopId = params.args.get('shopId')
    shop =  Shop.get(shopId)
    headers = createHeader(shop.accessToken)
    print('headers',headers)
    print('shop.url',shop.url)
    print('apiVersion',apiVersion)
    url = f"{shop.url}/admin/api/{apiVersion}/locations.json"
    res = requests.get(url, headers=headers)
    if res.status_code == 200:
        locations = res.json().get("locations", [])
        print("📍 Available Locations:")
        for loc in locations:
            print(f"- {loc['name']} | ID: {loc['id']} | Active: {loc['active']}")
        return locations
    else:
        print("❌ Failed to fetch locations: ", res.text)



# def connectProductToLocationAfterMapping(params:Params):
#     shopId = data.get('shopId')
#     productId =     data.get('productId')
#     platformProductId = data.get('platformProductId')
#     shop = getShopById(shopId, True)
#     enterpriseId = shop.get('enterpriseId')
#     accessToken = shop.get('accessToken')
#     url = shop.get('url')
#     headers = createHeader(accessToken)
#     fulfillmentService = getFulfillmentService(shopId)
#     if not fulfillmentService:
#         fulfillmentService = createFulfillmentService(dict(
#             shopId = shopId,
#             shop=shop,
#             currentUser = data.get('currentUser'),            
#         ))
#     variants = getShopifyProduct(url, platformProductId, headers)
#     if variants:
#         for variant in variants:
#             inventory_item_id = variant.get('inventory_item_id')
#             variantMapping = getVariantMapping(productId, str(variant.get('id')))
#             if not variant.get("sku"):
#                 print("No sku")
#                 print("generated sku", variantMapping.get("sku"))
#                 updateVariantSku(url, headers, variant.get('id'), variantMapping.get("sku"))
#             if enterpriseId != "5f9f1b0b0e2b4b0017e1b0a5":
#                 locationConnected = connectionInventoryLocation(url, headers, inventory_item_id, fulfillmentService.get('location_id'))
#             cost = None
#             try:
#                 cost = getItemCost(enterpriseId, variantMapping.get('blankProductId'), variantMapping.get('blankVariantId'))
#             except Exception as e:
#                 print(traceback.format_exc())
#             if type(cost) not in [int,float]: cost = 0
#             costSubmitted = updateItemCostOnShopify(url, headers, inventory_item_id,cost)
#             if not (locationConnected or costSubmitted): print("locationConnected", locationConnected,"costSubmitted",costSubmitted)
#     return []

from datetime import datetime


def getFulfillmentService(client:ShopifyGraphQLClient, enterpriseName=None):
    """
    Retrieves the fulfillment service for a given shop and validates if the location exists in Shopify.
    If the fulfillment service does not exist, it creates a new one.

    :param shop: ShopifyGraphQLClient instance
    :param shopId: The shop's ID
    :return: Fulfillment service data if valid, otherwise None
    """
    # Fetch fulfillment service from Firestore
    if not enterpriseName: 
        enterpriseName = Enterprise.get(client.shop.enterpriseId).name
    ref = db.collection("fulfillmentServicesGraphQL").document(client.id).get()
    if ref.exists:
        fulfillment_data = ref.to_dict()
        # print("FULFILLMENT DATA: ", fulfillment_data)
        fulfillment_id = fulfillment_data.get("id")
        # print("FULFILLMENT ID: ", fulfillment_id)
        if fulfillment_id:
            # **Step 2: Validate if the fulfillment service exists in Shopify**

            query = """
            query FulfillmentServiceShow($id: ID!) {
              fulfillmentService(id: $id) {
                    id
                    serviceName
                    callbackUrl
                    location {
                     legacyResourceId
                     id
                    }
              }
            }
            """
            variables = {"id": fulfillment_id}
            result = client.execute(query, variables)
            # print("FULFILLMENT SERVICE: ", result)
            # Check if fulfillment service exists in Shopify
            fulfillmentService = result.get("data", {}).get("fulfillmentService", {})
            if fulfillmentService: return fulfillmentService
    # If no valid fulfillment service exists, create a new one
    return createFulfillmentService(client=client, enterpriseName=enterpriseName)

def createFulfillmentService(client:ShopifyGraphQLClient, enterpriseName: str= "POD"):
    """
    Creates a new fulfillment service in Shopify via GraphQL and stores it in Firestore.

    :param shop: Shopify shop data
    """

    # Generate Fulfillment Service Name
    fulfillment_name = f"{enterpriseName} - Fulfillment Service"
    callback_url = f"https://riverr-enterprise-integrations-dot-{PROJECT_ID}.uc.r.appspot.com/shopify/fulfillment"

    # **Fulfillment Service Creation Mutation**
    mutation = """
        mutation fulfillmentServiceCreate($name: String!, $callbackUrl: URL!) {
            fulfillmentServiceCreate(name: $name, callbackUrl: $callbackUrl, trackingSupport: true, inventoryManagement: true) {
                fulfillmentService {
                    id
                    serviceName
                    callbackUrl
                    location {
                        id
                    }
                }
                userErrors {
                    field
                    message
                }
            }
        }
    """

    

    variables = {
        "name": fulfillment_name,
        "callbackUrl": callback_url
    }

    # **Execute GraphQL Request**
    result = client.execute(mutation, variables)
    # **Check for Errors**
    errors = result.get("data", {}).get("fulfillmentServiceCreate", {}).get("userErrors", [])
    if errors:
        print("FULFILLMENT SERVICE ERRORS: ", errors)
        raise API_Error(str(errors), 400)

    # **Extract New Fulfillment Service**
    fulfillment_service = result["data"]["fulfillmentServiceCreate"]["fulfillmentService"]
    # # **Save to Firestore**
    # fulfillment_data = {
    #     "id": fulfillment_service["id"],
    #     "name": fulfillment_service["serviceName"],
    #     "callback_url": fulfillment_service["callbackUrl"],
    #     "location_id": fulfillment_service["location"]["id"],
    # }
    db.collection("fulfillmentServicesGraphQL").document(client.id).set(fulfillment_service)
    return fulfillment_service

def createFulfillmentServiceRoute(params: Params):
    shopId = params.args.get('shopId')
    shop = Shop.get(shopId)
    client = ShopifyGraphQLClient(shop)
    enterprise = Enterprise.get(shop.enterpriseId)
    if enterprise: return createFulfillmentService(client, enterpriseName=enterprise.name)
    return None

from typing import List


def updateFulfillmentLocations(client: ShopifyGraphQLClient, productId: str, variants: List[Variant] = [], locationId: str = None, platformProductId: str = None):
    """
    Updates the fulfillment location of product variants in Shopify using the inventoryAdjustQuantities mutation.

    :param client: Shopify GraphQL client
    :param productId: The product ID
    :param variants: The product variants (optional)
    :param locationId: The location ID to update the inventory
    :param platformProductId: The Shopify platform product ID (optional)
    """

    # **Step 1: Fetch Variants If Not Provided**
    if not variants:
        variants = Variant.getAll(productId)

    # **Step 2: Get Location ID If Not Provided**
    if not locationId:
        locationId = getFulfillmentService(client).get("location").get("id")
    print('locationId:-',locationId)


    # **Step 3: Get Shopify Platform Product ID**
    if not platformProductId:
        platformProductId = Product.get(productId).platformProductId
    
    print('platformProductId:-',platformProductId)

    # **Step 4: Fetch Shopify Variants**
    shopify_variants = getShopifyProductVariants(client, platformProductId)

    # # **Step 5: Prepare Inventory Adjustment Mutation**

    mutation_parts = []
    for idx, variant in enumerate(shopify_variants):
        alias = f"inventoryActivate{idx}"
        mutation_parts.append(f"""
        {alias}: inventoryActivate(inventoryItemId: "{variant.get('inventoryItemId')}", locationId: "{locationId}") {{
          inventoryLevel {{
            id
          }}
          userErrors {{
            field
            message
          }}
        }}
        """)

    mutation = f"mutation inventoryActivateMultiple {{ {' '.join(mutation_parts)} }}"

    # **Step 2: Execute GraphQL Request**
    result = client.execute(mutation)
    print("RESULT: ", result)
    # **Step 3: Check for Errors**
    for idx, variant in enumerate(shopify_variants):
        alias = f"inventoryActivate{idx}"
        errors = result.get("data", {}).get(alias, {}).get("userErrors", [])
        if errors:
            print(f"❌ ERROR Activating Inventory Item {variant.get('inventoryItemId')}: {errors}")

    print("✅ Fulfillment locations updated successfully for all variants!")



# shop = Shop.get("ExKbzizKurp9hprjrT8C")
# client = ShopifyGraphQLClient(shop)

# updateFulfillmentLocations(client, "2ExKbzizKurp9hprjrT8C7084675072085")