import refreshTokenHelper from "../../../utils/refreshTokenHelper"
import errorHandlingHelper from "../../../utils/errorHandlingHelper"
import fetchHelper from "../../../utils/fetchHelper"

// GET /api/shopify/stocks?orderSourceId=123&variantIds=1,2,3
// Fetches current stock from Shopify for given SKUs
// Uses REST API: fetches all products to build SKU->inventory_item_id map, then fetches inventory levels
const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const query = getQuery(event)
  const orderSourceId = query.orderSourceId as string
  const variantIdsParam = query.variantIds as string

  if(!orderSourceId) {
    return { status: 400, message: 'orderSourceId is required' }
  }
  if(!variantIdsParam) {
    return { status: 400, message: 'variantIds is required' }
  }

  const skus = variantIdsParam.split(',').map(id => id.trim()).filter(Boolean)
  if(skus.length === 0) {
    return { status: 400, message: 'No valid SKUs provided' }
  }

  // Load order source to verify it's Shopify 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' }
  }
  if(os?.Marketplace?.identifier !== 'shopify') {
    return { status: 400, message: 'Selected Order Source is not Shopify' }
  }

  // Get Shopify credentials from order source
  const shopUrl = os?.marketplace_url || ''
  const accessToken = os?.marketplace_token || os?.marketplace_secret || ''

  if(!shopUrl) {
    return { status: 400, message: 'No marketplace_url configured for this Order Source' }
  }
  if(!accessToken) {
    return { status: 400, message: 'No marketplace_token or marketplace_secret configured for this Order Source' }
  }

  // Get Shopify location ID (optional - if not set, will get all locations)
  const locationId = os?.Shopify_Location_ID || null

  try {
    // Normalize shop URL
    let host = shopUrl.trim()
    if(!/^https?:\/\//i.test(host)) host = `https://${host}`
    host = host.replace(/\/$/, '')
    if(!host.includes('.myshopify.com') && !host.includes('/admin')) {
      const shopName = host.replace(/^https?:\/\//i, '').split('.')[0]
      host = `https://${shopName}.myshopify.com`
    }

    const apiBase = `${host}/admin/api/2024-01`

    const authHeaders = {
      'X-Shopify-Access-Token': accessToken,
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    }

    const stocks: Record<string, number> = {}
    const inventoryItemIds: Record<string, string> = {}
    const errors: Record<string, string> = {}

    // Initialize all requested SKUs with 0
    for(const sku of skus) {
      stocks[sku] = 0
    }

    // Create a Set for fast SKU lookup
    const skuSet = new Set(skus.map(s => s.toLowerCase()))

    // Step 1: Fetch ALL products with their variants to build SKU -> inventory_item_id map
    // Using since_id pagination (cursor-based) as page-based is deprecated
    // See: https://shopify.dev/docs/api/admin-rest/usage/pagination
    console.log('Fetching Shopify products to build SKU map...')
    const skuToInventoryItemMap: Record<string, { inventoryItemId: string, variantId: string }> = {}
    let sinceId = 0
    let hasMore = true
    const limit = 250 // Max allowed by Shopify
    let pageNum = 1

    while(hasMore) {
      try {
        // Use since_id for cursor-based pagination
        const productsUrl = `${apiBase}/products.json?limit=${limit}&since_id=${sinceId}`
        console.log(`Fetching products (since_id=${sinceId})...`)

        const productsRes: any = await $fetch(productsUrl, {
          method: 'GET',
          headers: authHeaders
        })

        const products = productsRes?.products || []
        console.log(`Got ${products.length} products on page ${pageNum}`)

        if(products.length === 0) {
          hasMore = false
          break
        }

        // Build SKU -> inventory_item_id map
        for(const product of products) {
          const variants = product.variants || []
          for(const variant of variants) {
            const variantSku = String(variant.sku || '').toLowerCase()
            if(variantSku && skuSet.has(variantSku)) {
              skuToInventoryItemMap[variantSku] = {
                inventoryItemId: String(variant.inventory_item_id),
                variantId: String(variant.id)
              }
            }
          }
          // Update since_id to the last product's ID for next page
          if(product.id) {
            sinceId = product.id
          }
        }

        // Check if we should continue (less than limit means last page)
        if(products.length < limit) {
          hasMore = false
        } else {
          pageNum++
          // Safety limit
          if(pageNum > 100) hasMore = false
        }
      } catch (err: any) {
        console.error(`Failed to fetch products (since_id=${sinceId}):`, err?.message || err)
        hasMore = false
      }
    }

    console.log(`Built SKU map with ${Object.keys(skuToInventoryItemMap).length} entries`)

    // Step 2: Fetch all locations
    const locationsMap: Record<string, { id: string, name: string, active: boolean }> = {}
    try {
      const locationsUrl = `${apiBase}/locations.json`
      const locationsRes: any = await $fetch(locationsUrl, {
        method: 'GET',
        headers: authHeaders
      })
      if(locationsRes?.locations && Array.isArray(locationsRes.locations)) {
        for(const loc of locationsRes.locations) {
          locationsMap[String(loc.id)] = {
            id: String(loc.id),
            name: loc.name || `Location ${loc.id}`,
            active: loc.active ?? true
          }
        }
        console.log(`Found ${Object.keys(locationsMap).length} Shopify locations`)
      }
    } catch (locErr: any) {
      console.log('Could not fetch locations:', locErr?.message)
    }

    // Step 3: Fetch inventory levels for all inventory_item_ids (from ALL locations)
    const inventoryItemIdsToFetch = Object.values(skuToInventoryItemMap).map(v => v.inventoryItemId)
    // Map: inventoryItemId -> { total: number, byLocation: { locationId: { qty, name } } }
    const inventoryLevelsMap: Record<string, { total: number, byLocation: Record<string, { qty: number, name: string }> }> = {}

    if(inventoryItemIdsToFetch.length > 0) {
      // Shopify allows max 50 inventory_item_ids per request
      const batchSize = 50
      for(let i = 0; i < inventoryItemIdsToFetch.length; i += batchSize) {
        const batch = inventoryItemIdsToFetch.slice(i, i + batchSize)
        try {
          // Fetch from all locations (no location_ids filter)
          const inventoryUrl = `${apiBase}/inventory_levels.json?inventory_item_ids=${batch.join(',')}`
          console.log(`Fetching inventory levels for ${batch.length} items...`)

          const inventoryRes: any = await $fetch(inventoryUrl, {
            method: 'GET',
            headers: authHeaders
          })

          const levels = inventoryRes?.inventory_levels || []
          for(const level of levels) {
            const itemId = String(level.inventory_item_id)
            const locId = String(level.location_id)
            const qty = Number(level.available || 0)
            const locName = locationsMap[locId]?.name || `Location ${locId}`

            if(!inventoryLevelsMap[itemId]) {
              inventoryLevelsMap[itemId] = { total: 0, byLocation: {} }
            }
            inventoryLevelsMap[itemId].total += qty
            inventoryLevelsMap[itemId].byLocation[locId] = { qty, name: locName }
          }
        } catch (invErr: any) {
          console.error(`Failed to fetch inventory levels:`, invErr?.message || invErr)
        }
      }
    }

    console.log(`Got inventory levels for ${Object.keys(inventoryLevelsMap).length} items`)

    // Step 4: Map back to SKUs with location breakdown
    const stocksByLocation: Record<string, Record<string, { qty: number, name: string }>> = {}

    for(const sku of skus) {
      const skuLower = sku.toLowerCase()
      const mapping = skuToInventoryItemMap[skuLower]
      if(mapping) {
        inventoryItemIds[sku] = mapping.inventoryItemId
        const invData = inventoryLevelsMap[mapping.inventoryItemId]
        stocks[sku] = invData?.total ?? 0
        if(invData?.byLocation && Object.keys(invData.byLocation).length > 0) {
          stocksByLocation[sku] = invData.byLocation
        }
      } else {
        errors[sku] = 'SKU not found in Shopify'
      }
    }

    return {
      status: 200,
      stocks,
      stocksByLocation, // Per-SKU breakdown by location
      inventoryItemIds,
      locations: locationsMap, // All available locations
      errors: Object.keys(errors).length > 0 ? errors : undefined,
      skuCount: skus.length,
      matchedCount: Object.keys(skuToInventoryItemMap).length
    }

  } catch (err: any) {
    console.error('Shopify stocks error:', err)
    const data = errorHandlingHelper(err?.data ?? err, err?.data ?? err)
    return {
      status: Number(data?.status || 500),
      message: data?.message || 'Failed to fetch Shopify stocks'
    }
  }
}

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
    }
  }
})
