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

// GET /api/shopify/locations?orderSourceId=123
// Returns all Shopify locations for the shop plus a default location to preselect.
// Default priority: Shopify_Location_ID on the order source > shop primary location > first active.
const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const query = getQuery(event)
  const orderSourceId = query.orderSourceId as string

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

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

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

  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 locations: Record<string, { id: string, name: string, active: boolean }> = {}
    let locationsQueryError = ''

    // Preferred: locations.json (requires the read_locations scope)
    try {
      const locationsRes: any = await $fetch(`${apiBase}/locations.json`, {
        method: 'GET',
        headers: authHeaders
      })
      for(const loc of (locationsRes?.locations || [])) {
        locations[String(loc.id)] = {
          id: String(loc.id),
          name: loc.name || `Location ${loc.id}`,
          active: loc.active ?? true
        }
      }
    } catch (locErr: any) {
      locationsQueryError = locErr?.data?.errors || locErr?.message || String(locErr)
      console.log('shopify: locations.json failed, trying inventory-level fallback:', locationsQueryError)
    }

    // Fallback: derive location IDs from inventory levels of a sample of products.
    // inventory_levels.json needs only read_inventory and returns plain location_id
    // values (names are not available without read_locations).
    if(Object.keys(locations).length === 0) {
      try {
        const productsRes: any = await $fetch(`${apiBase}/products.json?limit=50&fields=id,variants`, {
          method: 'GET',
          headers: authHeaders
        })
        const itemIds: string[] = []
        for(const product of (productsRes?.products || [])) {
          for(const variant of (product.variants || [])) {
            if(variant.inventory_item_id) itemIds.push(String(variant.inventory_item_id))
            if(itemIds.length >= 50) break
          }
          if(itemIds.length >= 50) break
        }
        if(itemIds.length > 0) {
          const inventoryRes: any = await $fetch(`${apiBase}/inventory_levels.json?inventory_item_ids=${itemIds.join(',')}`, {
            method: 'GET',
            headers: authHeaders
          })
          for(const level of (inventoryRes?.inventory_levels || [])) {
            const locId = String(level.location_id)
            if(!locations[locId]) {
              locations[locId] = { id: locId, name: `Location ${locId}`, active: true }
            }
          }
        }
        if(Object.keys(locations).length > 0) {
          console.log(`shopify: Derived ${Object.keys(locations).length} location(s) from inventory levels`)
        }
      } catch (scanErr: any) {
        console.log('shopify: inventory-level location fallback failed:', scanErr?.message)
        if(!locationsQueryError) locationsQueryError = scanErr?.data?.errors || scanErr?.message || String(scanErr)
      }
    }

    if(Object.keys(locations).length === 0) {
      return {
        status: 400,
        message: `No Shopify locations accessible${locationsQueryError ? ` — ${typeof locationsQueryError === 'object' ? JSON.stringify(locationsQueryError) : locationsQueryError}` : ''}. Grant the app the read_locations scope, or set Shopify_Location_ID on the order source.`,
        locations: {},
        defaultLocationId: ''
      }
    }

    // The shop's primary location is the natural default when none is configured
    let primaryLocationId = ''
    try {
      const shopRes: any = await $fetch(`${apiBase}/shop.json?fields=primary_location_id`, {
        method: 'GET',
        headers: authHeaders
      })
      if(shopRes?.shop?.primary_location_id) {
        primaryLocationId = String(shopRes.shop.primary_location_id)
      }
    } catch (shopErr: any) {
      console.log('shopify: Could not fetch shop primary location:', shopErr?.message)
    }

    // iDempiere returns the ColumnName casing verbatim — the column is shopify_location_id
    const osLocationRaw = os?.shopify_location_id ?? os?.Shopify_Location_ID
    const osLocationId = osLocationRaw ? String(osLocationRaw) : ''
    // A configured default always appears in the list, even if the (possibly
    // fallback-derived) location scan didn't surface it
    if(osLocationId && !locations[osLocationId]) {
      locations[osLocationId] = { id: osLocationId, name: `Location ${osLocationId}`, active: true }
    }
    const active = Object.values(locations).filter((l) => l.active)
    const defaultFromOrderSource = !!(osLocationId && locations[osLocationId])
    let defaultLocationId = defaultFromOrderSource ? osLocationId : ''
    if(!defaultLocationId && primaryLocationId && locations[primaryLocationId]?.active) {
      defaultLocationId = primaryLocationId
    }
    if(!defaultLocationId) {
      defaultLocationId = active[0]?.id || ''
    }

    return {
      status: 200,
      locations,
      defaultLocationId,
      defaultFromOrderSource
    }
  } catch (err: any) {
    console.error('shopify locations error:', err?.message || err)
    return {
      status: Number(err?.status || err?.response?.status || 500),
      message: err?.message || 'Failed to fetch Shopify locations',
      locations: {},
      defaultLocationId: ''
    }
  }
}

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