import { string } from 'alga-js'

// DHL ROPC tokens are app-level (not per-user), so we share one cached token across
// all operators hitting the same Node process. TTL of 50 minutes leaves a safety
// margin under DHL's typical 1-hour token lifetime. The per-user cookie is kept
// as a fallback so a fresh process can pick up a still-valid token without re-auth.
const TOKEN_TTL_MS = 50 * 60 * 1000
const COOKIE_MAX_AGE_S = 50 * 60
let cachedToken: string | null = null
let cachedTokenExpiry = 0

const getToken = async () => {
  const config = useRuntimeConfig()

  return await $fetch(config.api.dhlurl+'/account/auth/ropc/v1/token', {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: `grant_type=password&username=${string.urlEncode(config.api.dhluser)}&password=${string.urlEncode(config.api.dhlpass)}&client_id=${string.urlEncode(config.api.dhlkey)}&client_secret=${string.urlEncode(config.api.dhlsecret)}`
  })
}

const persistToken = (event: any, token: string) => {
  cachedToken = token
  cachedTokenExpiry = Date.now() + TOKEN_TTL_MS
  setCookie(event, 'logship_bdhtl', token, { maxAge: COOKIE_MAX_AGE_S })
}

const resolveToken = async (event: any): Promise<string> => {
  if (cachedToken && cachedTokenExpiry > Date.now()) {
    return cachedToken
  }
  const cookieToken = getCookie(event, 'logship_bdhtl') ?? ''
  if (cookieToken !== '') {
    return cookieToken
  }
  const res = await getToken()
  if (res?.access_token) {
    persistToken(event, res.access_token)
    return res.access_token
  }
  return ''
}

export default async function dhlHelper(event: any, url: string, method: string = 'GET', body: any) {
  const config = useRuntimeConfig()
  let token = await resolveToken(event)

  let options: any = {}
  if(body) {
    options = {
      ...options,
      body: body
    }
  }

  try {
    return await $fetch(config.api.dhlurl+'/'+url, {
      method: method,
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        Authorization: 'Bearer ' + token
      },
      ...options
    })
  } catch(err: any) {
    // If it's a validation error (400), don't retry with new token - it won't help
    if(err?.statusCode === 400 || err?.status === 400) {
      console.error('[DHL API Error] Validation error (400):', JSON.stringify(err?.data, null, 2))
      throw err
    }

    // Invalidate cache: token might be revoked even though our TTL says it's good.
    cachedToken = null
    cachedTokenExpiry = 0

    const res2 = await getToken()
    if(res2?.access_token) {
      token = res2.access_token
      persistToken(event, token)
    }

    return await $fetch(config.api.dhlurl+'/'+url, {
      method: method,
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        Authorization: 'Bearer ' + token
      },
      ...options
    })
  }

}