import refreshTokenHelper from "../../../utils/refreshTokenHelper"
import errorHandlingHelper from "../../../utils/errorHandlingHelper"
import fetchHelper from "../../../utils/fetchHelper"
import { getShopifyNewAccessToken, shopifyNewGraphQL, parseShopifyGid, buildShopifyGid } from "../../../utils/shopifyNewAuthHelper"

// POST /api/shopify-new/stocks/sync
// Syncs local qty to Shopify via GraphQL inventorySetQuantities mutation
// Body: { orderSourceId, variantId (SKU), inventoryItemId?, quantity, sku?, productId?, locationId? }
// Returns same response shape as /api/shopify/stocks/sync for frontend compatibility
const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const body = await readBody(event)

  const { orderSourceId, variantId, quantity, sku, productId, locationId: bodyLocationId } = body
  let { inventoryItemId } = body

  if(!orderSourceId) {
    return { status: 400, message: 'orderSourceId is required', success: false }
  }
  if(!variantId) {
    return { status: 400, message: 'variantId (SKU) is required', success: false }
  }
  if(quantity === undefined || quantity === null) {
    return { status: 400, message: 'quantity is required', success: false }
  }

  // Load order source to verify it's shopify-new and get credentials
  const os: any = await fetchHelper(event, `models/c_ordersource/${orderSourceId}`, 'GET', token, null)
  if(!os) {
    return { status: 404, message: 'Order Source not found', success: false }
  }
  if(os?.Marketplace?.identifier !== 'shopify-new') {
    return { status: 400, message: 'Selected Order Source is not Shopify-New', success: false }
  }

  try {
    const { accessToken, graphqlUrl } = await getShopifyNewAccessToken(os)
    const targetQty = Number(quantity)
    const skuToFind = String(variantId).toLowerCase()

    // If inventoryItemId is provided and already a GID, use it directly
    if(inventoryItemId) {
      console.log(`shopify-new: Using provided inventoryItemId: ${inventoryItemId} for SKU "${variantId}"`)
    }

    // If inventoryItemId is not provided, look up variant by SKU via GraphQL
    if(!inventoryItemId) {
      console.log(`shopify-new: Searching for SKU "${skuToFind}" in Shopify...`)

      const variantQuery = `query($skuQuery: String!) {
        productVariants(first: 1, query: $skuQuery) {
          edges {
            node {
              id
              sku
              inventoryItem {
                id
              }
              product {
                id
              }
            }
          }
        }
      }`

      const variantRes = await shopifyNewGraphQL(graphqlUrl, accessToken, variantQuery, {
        skuQuery: `sku:${variantId}`
      })

      const variantEdges = variantRes?.data?.productVariants?.edges || []
      if(variantEdges.length > 0) {
        inventoryItemId = variantEdges[0].node?.inventoryItem?.id
        console.log(`shopify-new: Found SKU "${skuToFind}" -> inventoryItemId: ${inventoryItemId}`)
      }
    }

    if(!inventoryItemId) {
      return {
        status: 400,
        success: false,
        message: `Could not find variant with SKU "${variantId}" in Shopify.`,
        variantId
      }
    }

    // Resolve location ID
    // Priority: body param > order source config > fetch from API
    const osLocationId = os?.Shopify_Location_ID || null
    let effectiveLocationId = bodyLocationId || osLocationId

    if(!effectiveLocationId) {
      // Try to fetch first active location
      try {
        const locQuery = `{
          locations(first: 5) {
            edges {
              node {
                id
                name
                isActive
              }
            }
          }
        }`
        const locRes = await shopifyNewGraphQL(graphqlUrl, accessToken, locQuery)
        const locationEdges = locRes?.data?.locations?.edges || []
        const activeLocation = locationEdges.find((e: any) => e.node.isActive) || locationEdges[0]
        if(activeLocation) {
          effectiveLocationId = parseShopifyGid(activeLocation.node.id)
          console.log(`shopify-new: Using location ${effectiveLocationId} (${activeLocation.node.name})`)
        }
      } catch (locErr: any) {
        console.error('shopify-new: Failed to fetch locations:', locErr?.message)
        return {
          status: 400,
          success: false,
          message: 'Could not determine Shopify location. Please configure Shopify_Location_ID on the order source.',
          variantId
        }
      }
    }

    if(!effectiveLocationId) {
      return {
        status: 400,
        success: false,
        message: 'No Shopify location found. Please configure Shopify_Location_ID on the order source.',
        variantId
      }
    }

    // Build GIDs for the mutation
    const inventoryItemGid = buildShopifyGid('InventoryItem', inventoryItemId.includes('gid://') ? parseShopifyGid(inventoryItemId) : inventoryItemId)
    const locationGid = buildShopifyGid('Location', effectiveLocationId)

    // Set inventory via inventorySetQuantities mutation
    const setMutation = `mutation inventorySetQuantities($input: InventorySetQuantitiesInput!) {
      inventorySetQuantities(input: $input) {
        inventoryAdjustmentGroup {
          createdAt
          changes {
            name
            delta
            quantityAfterChange
          }
        }
        userErrors {
          field
          message
        }
      }
    }`

    const setVariables = {
      input: {
        name: "available",
        reason: "correction",
        quantities: [
          {
            inventoryItemId: inventoryItemGid,
            locationId: locationGid,
            quantity: targetQty
          }
        ]
      }
    }

    console.log('shopify-new: inventory set request:', JSON.stringify(setVariables))

    const result = await shopifyNewGraphQL(graphqlUrl, accessToken, setMutation, setVariables)

    // Check for userErrors
    const userErrors = result?.data?.inventorySetQuantities?.userErrors || []
    if(userErrors.length > 0) {
      const errMsg = userErrors.map((e: any) => `${e.field}: ${e.message}`).join('; ')
      return {
        status: 400,
        success: false,
        message: `Shopify error: ${errMsg}`,
        variantId,
        shopifyResponse: result?.data
      }
    }

    // Get the updated quantity from the response
    const changes = result?.data?.inventorySetQuantities?.inventoryAdjustmentGroup?.changes || []
    const updatedStock = changes.length > 0 ? changes[0].quantityAfterChange : targetQty

    console.log('shopify-new: inventory set response:', JSON.stringify(result?.data).slice(0, 800))

    return {
      status: 200,
      success: true,
      message: `Stock set to ${updatedStock} for SKU "${variantId}" at location ${effectiveLocationId}`,
      variantId,
      inventoryItemId: inventoryItemGid,
      quantity: targetQty,
      updatedStock,
      locationId: effectiveLocationId,
      shopifyResponse: result?.data
    }

  } catch (err: any) {
    const errData = err?.data || err
    const errMsg = errData?.message || errData?.errors || err?.message || 'Failed to sync stock to Shopify-New'
    const errStatus = err?.status || err?.response?.status || errData?.status || 500

    console.error('shopify-new stock sync error:', {
      variantId,
      quantity,
      error: errData
    })

    return {
      status: errStatus,
      success: false,
      message: typeof errMsg === 'object' ? JSON.stringify(errMsg) : errMsg,
      error: errData,
      variantId
    }
  }
}

export default defineEventHandler(async (event) => {
  try {
    return await handleFunc(event)
  } catch (err: any) {
    try {
      const authToken = await refreshTokenHelper(event)
      return await handleFunc(event, authToken)
    } catch (error: any) {
      const data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
      if([401, 402, 403, 407].includes(Number(data.status))) {
        //@ts-ignore
        setCookie(event, 'user', null)
      }
      return { ...data, success: false }
    }
  }
})
