import {
  generateRegistrationOptions,
  verifyRegistrationResponse,
  generateAuthenticationOptions,
  verifyAuthenticationResponse,
} from '@simplewebauthn/server'
import type {
  RegistrationResponseJSON,
  AuthenticationResponseJSON,
} from '@simplewebauthn/server'

export interface RpConfig {
  rpID: string
  rpName: string
  origin: string
}

export function getRpConfig(): RpConfig {
  const config = useRuntimeConfig()
  const rpID = (config as any).webauthn?.rpId
  const rpName = (config as any).webauthn?.rpName ?? 'LogShip ERP'
  const origin = (config as any).webauthn?.origin
  if (!rpID || !origin) {
    throw new Error('WEBAUTHN_RP_ID and WEBAUTHN_ORIGIN env vars must be set')
  }
  return { rpID, rpName, origin }
}

// numeric ad_user.id encoded as Uint8Array for the WebAuthn userHandle
function encodeUserHandle(userId: number): Uint8Array {
  // Buffer.from(...) returns a Buffer (extends Uint8Array<ArrayBuffer>); the
  // TextEncoder path produces Uint8Array<ArrayBufferLike> which TS rejects
  // for the simplewebauthn typing on userID.
  return Buffer.from(String(userId), 'utf8')
}

export function decodeUserHandle(handle: string | undefined | null): number | null {
  if (!handle) return null
  try {
    const decoded = Buffer.from(handle, 'base64url').toString('utf8')
    const n = Number(decoded)
    return Number.isFinite(n) && n > 0 ? n : null
  } catch {
    return null
  }
}

export async function buildRegistrationOptions(opts: {
  userId: number
  userName: string
  userDisplayName?: string
  excludeCredentialIds?: string[]
}) {
  const { rpID, rpName } = getRpConfig()
  return generateRegistrationOptions({
    rpName,
    rpID,
    userName: opts.userName,
    userID: encodeUserHandle(opts.userId) as any,
    userDisplayName: opts.userDisplayName ?? opts.userName,
    attestationType: 'none',
    authenticatorSelection: {
      residentKey: 'required',
      requireResidentKey: true,
      userVerification: 'preferred',
    },
    excludeCredentials: (opts.excludeCredentialIds ?? []).map(id => ({ id })),
  })
}

export async function verifyRegistration(opts: {
  response: RegistrationResponseJSON
  expectedChallenge: string
}) {
  const { rpID, origin } = getRpConfig()
  return verifyRegistrationResponse({
    response: opts.response,
    expectedChallenge: opts.expectedChallenge,
    expectedOrigin: origin,
    expectedRPID: rpID,
    requireUserVerification: false,
  })
}

export async function buildAuthenticationOptions() {
  const { rpID } = getRpConfig()
  return generateAuthenticationOptions({
    rpID,
    userVerification: 'preferred',
    // empty allowCredentials → discoverable (resident) credential flow
  })
}

export async function verifyAuthentication(opts: {
  response: AuthenticationResponseJSON
  expectedChallenge: string
  credential: { id: string; publicKey: Uint8Array; counter: number; transports?: any[] }
}) {
  const { rpID, origin } = getRpConfig()
  return verifyAuthenticationResponse({
    response: opts.response,
    expectedChallenge: opts.expectedChallenge,
    expectedOrigin: origin,
    expectedRPID: rpID,
    credential: opts.credential as any,
    requireUserVerification: false,
  })
}
