import { string } from 'alga-js'
import refreshTokenHelper from "../../../utils/refreshTokenHelper"
import fetchHelper from "../../../utils/fetchHelper"
import getTokenHelper from "../../../utils/getTokenHelper"

const LWA_TOKEN_URL = 'https://api.amazon.com/auth/o2/token'
const SP_API_BASE_URL = 'https://sellingpartnerapi-eu.amazon.com'

export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig()
  const query = getQuery(event)
  const code = query.spapi_oauth_code as string | undefined
  const state = query.state as string | undefined // UID of the order source
  const sellingPartnerId = query.selling_partner_id as string | undefined

  // If the merchant declined or an error occurred on the Amazon side
  if (!code || !state) {
    const errorMsg = encodeURIComponent(query.error_description as string || 'Amazon authorization was declined or failed')
    return sendRedirect(event, `/settings/order-sources?oauth_error=${errorMsg}`, 302)
  }

  if (!config.api.amazonLwaClientId || !config.api.amazonLwaClientSecret || !config.api.amazonOauthRedirectUri) {
    const errorMsg = encodeURIComponent('Amazon OAuth is not configured on the server')
    return sendRedirect(event, `/settings/order-sources?oauth_error=${errorMsg}`, 302)
  }

  // Look up the order source by UID (validates the state param)
  let orderSource: any = null
  let token: string | null = null
  try {
    token = await getTokenHelper(event)
    const res: any = await fetchHelper(
      event,
      `models/c_ordersource?$filter=${string.urlEncode(`C_OrderSource_UU eq '${state}'`)}`,
      'GET',
      token,
      null
    )
    orderSource = res?.records?.[0]
  } catch (err: any) {
    try {
      token = await refreshTokenHelper(event)
      const res: any = await fetchHelper(
        event,
        `models/c_ordersource?$filter=${string.urlEncode(`C_OrderSource_UU eq '${state}'`)}`,
        'GET',
        token,
        null
      )
      orderSource = res?.records?.[0]
    } catch (error: any) {
      const errorMsg = encodeURIComponent('Failed to fetch order source during OAuth callback')
      return sendRedirect(event, `/settings/order-sources?oauth_error=${errorMsg}`, 302)
    }
  }

  if (!orderSource) {
    const errorMsg = encodeURIComponent('Order source not found')
    return sendRedirect(event, `/settings/order-sources?oauth_error=${errorMsg}`, 302)
  }

  const orderSourceId = orderSource.id

  // Exchange the LWA authorization code for a refresh token (our public app's credentials)
  let tokenResponse: any = null
  try {
    tokenResponse = await $fetch(LWA_TOKEN_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        grant_type: 'authorization_code',
        code: code,
        redirect_uri: String(config.api.amazonOauthRedirectUri),
        client_id: String(config.api.amazonLwaClientId),
        client_secret: String(config.api.amazonLwaClientSecret),
      }).toString(),
    })
  } catch (err: any) {
    console.error('Amazon LWA token exchange error:', err?.data || err?.message || err)
    const errorMsg = encodeURIComponent(err?.data?.error_description || 'Failed to exchange authorization code for tokens')
    return sendRedirect(event, `/settings/order-sources/${orderSourceId}/edit?oauth_error=${errorMsg}`, 302)
  }

  if (!tokenResponse?.refresh_token) {
    const errorMsg = encodeURIComponent('Amazon did not return a refresh token')
    return sendRedirect(event, `/settings/order-sources/${orderSourceId}/edit?oauth_error=${errorMsg}`, 302)
  }

  // Persist onto the order source: our app's LWA credentials + the merchant's refresh
  // token (plain string — what every Amazon SP-API consumer expects in marketplace_token).
  // SHOPWARE_KEY/SECRET are written too so the legacy column pair stays in sync with
  // what the edit form reads/writes.
  const updatePayload: any = {
    marketplace_key: String(config.api.amazonLwaClientId),
    SHOPWARE_KEY: String(config.api.amazonLwaClientId),
    marketplace_secret: String(config.api.amazonLwaClientSecret),
    SHOPWARE_SECRET: String(config.api.amazonLwaClientSecret),
    marketplace_token: String(tokenResponse.refresh_token),
    tableName: 'c_ordersource',
  }
  if (sellingPartnerId) {
    updatePayload.amazon_merchant_id = sellingPartnerId
  }
  // Ensure the SP-API base URL is set — Laravel's env fallback is the SANDBOX endpoint.
  const currentUrl = String(orderSource.marketplace_url || '')
  if (!currentUrl.startsWith('https://sellingpartnerapi')) {
    updatePayload.marketplace_url = SP_API_BASE_URL
  }

  try {
    await fetchHelper(event, `models/c_ordersource/${orderSourceId}`, 'PUT', token, updatePayload)
  } catch (err: any) {
    try {
      token = await refreshTokenHelper(event)
      await fetchHelper(event, `models/c_ordersource/${orderSourceId}`, 'PUT', token, updatePayload)
    } catch (error: any) {
      console.error('Failed to save Amazon tokens:', error?.data || error?.message || error)
      const errorMsg = encodeURIComponent('Tokens obtained but failed to save to order source')
      return sendRedirect(event, `/settings/order-sources/${orderSourceId}/edit?oauth_error=${errorMsg}`, 302)
    }
  }

  return sendRedirect(event, `/settings/order-sources/${orderSourceId}/edit?oauth_success=amazon`, 302)
})
