import { verifyRegistration } from '../../../utils/webauthnHelper'
import { consumeChallenge } from '../../../utils/webauthnChallengeStore'
import { readCredentials, writeCredentials, type WebAuthnKeyEntry } from '../../../utils/adUserCredentials'
import { encryptPassword } from '../../../utils/passwordCipher'
import fetchHelper from '../../../utils/fetchHelper'

export default defineEventHandler(async (event) => {
  const userIdRaw = getCookie(event, 'logship_user_id')
  const token = getCookie(event, 'logship_it')
  const userId = Number(userIdRaw)
  if (!userId || !token) {
    throw createError({ statusCode: 401, statusMessage: 'Not authenticated' })
  }

  const body = await readBody(event)
  const response = body?.response
  const nickname = String(body?.nickname ?? 'Security Key').slice(0, 64) || 'Security Key'

  if (!response?.response?.clientDataJSON) {
    throw createError({ statusCode: 400, statusMessage: 'Missing registration response' })
  }

  // Decode challenge from clientDataJSON
  const clientDataStr = Buffer.from(response.response.clientDataJSON, 'base64url').toString('utf8')
  const clientData = JSON.parse(clientDataStr)
  const challenge: string = clientData.challenge

  const entry = consumeChallenge(event, 'register', challenge)
  if (!entry || entry.userId !== userId) {
    throw createError({ statusCode: 400, statusMessage: 'Challenge expired or invalid' })
  }

  const verification = await verifyRegistration({ response, expectedChallenge: challenge })
  if (!verification.verified || !verification.registrationInfo) {
    throw createError({ statusCode: 400, statusMessage: 'Registration verification failed' })
  }

  const info = verification.registrationInfo
  const cred = info.credential

  const newKey: WebAuthnKeyEntry = {
    credentialId: cred.id,
    publicKey: Buffer.from(cred.publicKey).toString('base64'),
    counter: cred.counter,
    transports: cred.transports as string[] | undefined,
    nickname,
    createdAt: Date.now(),
    deviceType: info.credentialDeviceType,
    backedUp: info.credentialBackedUp,
  }

  const existing = await readCredentials(event, userId, token)

  // Capture the iDempiere password from ad_user via REST (using the user's own
  // token, which is authorized to read their own record). The Password column
  // is returned in plaintext by iDempiere REST, which is exactly what we need
  // to feed back into auth/tokens during a future passkey login.
  let password = existing.password
  if (!password) {
    try {
      const rec: any = await fetchHelper(event, 'models/ad_user/' + userId + '?$select=password', 'GET', token, null)
      const plain: string | undefined = rec?.Password ?? rec?.password
      if (plain) password = encryptPassword(plain)
    } catch {
      // leave password null; registration will fail loudly below
    }
  }
  if (!password) {
    throw createError({
      statusCode: 400,
      statusMessage: 'Could not capture password from ad_user — passkey not enrolled',
    })
  }

  const payload = {
    keys: [...existing.keys.filter(k => k.credentialId !== newKey.credentialId), newKey],
    password,
  }

  await writeCredentials(event, userId, payload, token)

  return {
    status: 200,
    credentialId: newKey.credentialId,
    nickname: newKey.nickname,
    passwordCaptured: !!password,
  }
})
