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

// GET /api/plentyone/stocks?orderSourceId=123&variationIds=1,2,3
// Fetches current stock from PlentyOne for given variation IDs
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 variationIdsParam = query.variationIds as string

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

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

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

  // Get PlentyOne credentials from order source
  const baseUrl = os?.marketplace_url || os?.SHOPWARE_URL || ''
  const clientId = os?.marketplace_key || ''
  const clientSecret = os?.marketplace_secret || ''

  if(!baseUrl) {
    return { status: 400, message: 'No marketplace_url configured for this Order Source' }
  }
  if(!clientId || !clientSecret) {
    return { status: 400, message: 'No marketplace_key or marketplace_secret configured for this Order Source' }
  }

  // Get PlentyOne warehouse ID (default: 102)
  const warehouseId = os?.PlentyOne_Warehouse_ID || 102

  try {
    // Normalize base URL
    let host = baseUrl.trim()
    if(!/^https?:\/\//i.test(host)) host = `https://${host}`
    host = host.replace(/\/$/, '')
    // Remove /rest suffix if present for token endpoint
    const baseHost = host.replace(/\/rest\/?$/, '')

    // Get OAuth access token from PlentyOne
    const tokenUrl = `${baseHost}/rest/login`
    let accessToken = ''
    try {
      const tokenRes: any = await $fetch(tokenUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        },
        body: {
          username: clientId,
          password: clientSecret
        }
      })
      accessToken = tokenRes?.accessToken || tokenRes?.access_token || ''
    } catch (tokenErr: any) {
      console.error('PlentyOne OAuth error:', tokenErr?.data || tokenErr?.message)
      return { status: 401, message: 'Failed to authenticate with PlentyOne. Check marketplace_key and marketplace_secret.' }
    }

    if(!accessToken) {
      return { status: 401, message: 'No access token received from PlentyOne' }
    }

    // Use baseHost for API calls (without /rest suffix, we'll add it)
    const apiBase = `${baseHost}/rest`

    // Fetch all stock for the warehouse, then filter by variation IDs
    // GET /rest/stockmanagement/warehouses/{warehouseId}/stock
    const stocks: Record<string, number> = {}
    const itemIds: Record<string, number> = {} // Map variationId -> itemId for sync endpoint
    const errors: Record<string, string> = {}

    // Initialize all requested variations with 0
    for(const varId of variationIds) {
      stocks[varId] = 0
    }

    // Create a Set for fast lookup
    const variationIdSet = new Set(variationIds.map(id => String(id)))

    // Fetch warehouse stock with pagination
    let page = 1
    const itemsPerPage = 250
    let hasMore = true
    let debugResponse = null

    while(hasMore) {
      try {
        const stockUrl = `${apiBase}/stockmanagement/warehouses/${warehouseId}/stock?page=${page}&itemsPerPage=${itemsPerPage}`

        const stockRes: any = await $fetch(stockUrl, {
          method: 'GET',
          headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/json',
            'Accept': 'application/json'
          }
        })

        // Save first response for debugging
        if(page === 1) {
          debugResponse = {
            url: stockUrl,
            firstItems: Array.isArray(stockRes) ? stockRes.slice(0, 3) :
                        stockRes?.entries ? stockRes.entries.slice(0, 3) : stockRes
          }
        }

        // Parse the response
        let entries: any[] = []
        if(Array.isArray(stockRes)) {
          entries = stockRes
        } else if(stockRes?.entries && Array.isArray(stockRes.entries)) {
          entries = stockRes.entries
        }

        // Process entries and match with our variation IDs
        for(const entry of entries) {
          const entryVarId = String(entry?.variationId || entry?.variation_id || '')
          if(variationIdSet.has(entryVarId)) {
            // Add physical stock (or net stock as fallback)
            const qty = Number(entry?.stockPhysical || entry?.physicalStock || entry?.stockNet || entry?.netStock || entry?.quantity || 0)
            stocks[entryVarId] = (stocks[entryVarId] || 0) + qty
            // Store itemId for sync endpoint
            if(entry?.itemId) {
              itemIds[entryVarId] = Number(entry.itemId)
            }
          }
        }

        // Check if there are more pages
        if(entries.length < itemsPerPage) {
          hasMore = false
        } else {
          page++
          // Safety limit to prevent infinite loops
          if(page > 100) hasMore = false
        }
      } catch (err: any) {
        console.error('Failed to fetch warehouse stock:', err?.message || err)
        hasMore = false

        // If warehouse endpoint fails, try individual variation lookups as fallback
        if(page === 1) {
          debugResponse = { error: err?.message, url: `${apiBase}/stockmanagement/warehouses/${warehouseId}/stock` }

          // Fallback: try to get stock per variation
          for(const varId of variationIds) {
            try {
              const varStockUrl = `${apiBase}/stockmanagement/stock?variationId=${varId}&warehouseId=${warehouseId}`
              const varRes: any = await $fetch(varStockUrl, {
                method: 'GET',
                headers: {
                  'Authorization': `Bearer ${accessToken}`,
                  'Content-Type': 'application/json',
                  'Accept': 'application/json'
                }
              })

              if(Array.isArray(varRes) && varRes.length > 0) {
                stocks[varId] = varRes.reduce((sum: number, e: any) =>
                  sum + Number(e?.stockPhysical || e?.physicalStock || e?.stockNet || 0), 0)
              } else if(varRes?.stockPhysical !== undefined) {
                stocks[varId] = Number(varRes.stockPhysical)
              }
            } catch (varErr: any) {
              errors[varId] = varErr?.message || 'Failed'
            }
          }
        }
      }
    }

    return {
      status: 200,
      stocks,
      itemIds, // Map variationId -> itemId for sync endpoint
      errors: Object.keys(errors).length > 0 ? errors : undefined,
      warehouseId,
      variationCount: variationIds.length,
      _debug: debugResponse // Shows raw API response for debugging
    }

  } catch (err: any) {
    const data = errorHandlingHelper(err?.data ?? err, err?.data ?? err)
    return {
      status: Number(data?.status || 500),
      message: data?.message || 'Failed to fetch PlentyOne 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
    }
  }
})
