/**
 * PasskeyButton — standalone passkey authenticate/register CTA.
 *
 * Lightweight button (≤ 40 lines of logic) that calls usePasskey().authenticate()
 * or register() based on the mode prop.  Disabled when the browser does not
 * support WebAuthn.
 */
import * as React from 'react'

import { Button, type ButtonProps } from '../primitives/button'
import { usePasskey } from '../hooks/usePasskey'
import type {
  WebAuthnRegistrationOptions,
  WebAuthnAuthenticationOptions,
  RegistrationCredential,
  AuthenticationCredential,
} from '../hooks/usePasskey'

export interface PasskeyButtonProps extends Omit<ButtonProps, 'onClick' | 'disabled' | 'loading'> {
  /** Whether to authenticate with an existing passkey or register a new one. */
  mode?: 'authenticate' | 'register'
  /** Options forwarded to the underlying WebAuthn call. */
  passkeyOptions?: WebAuthnAuthenticationOptions | WebAuthnRegistrationOptions
  /** Called with the credential on success. */
  onSuccess?: (credential: AuthenticationCredential | RegistrationCredential) => void
  /** Called when the WebAuthn operation throws. */
  onError?: (error: unknown) => void
}

export function PasskeyButton({
  mode = 'authenticate',
  passkeyOptions,
  onSuccess,
  onError,
  children,
  ...buttonProps
}: PasskeyButtonProps) {
  const { isSupported, authenticate, register } = usePasskey()
  const [pending, setPending] = React.useState(false)

  async function handleClick() {
    if (!isSupported) return
    setPending(true)
    try {
      let credential: AuthenticationCredential | RegistrationCredential
      if (mode === 'register') {
        credential = await register((passkeyOptions ?? {}) as WebAuthnRegistrationOptions)
      } else {
        credential = await authenticate((passkeyOptions ?? {}) as WebAuthnAuthenticationOptions)
      }
      onSuccess?.(credential)
    } catch (err: unknown) {
      onError?.(err)
    } finally {
      setPending(false)
    }
  }

  const defaultLabel = mode === 'register' ? 'Register passkey' : 'Sign in with passkey'
  // Only set aria-label when there are no children (children provide the accessible name).
  const ariaLabel =
    buttonProps['aria-label'] ??
    (children === null || children === undefined ? defaultLabel : undefined)

  return (
    <Button
      {...buttonProps}
      disabled={!isSupported}
      loading={pending}
      onClick={() => void handleClick()}
      {...(ariaLabel !== undefined ? { 'aria-label': ariaLabel } : {})}
    >
      {children ?? defaultLabel}
    </Button>
  )
}
