// Passkey management for settings page
import { bufferToBase64url, base64urlToBuffer, getCsrfToken } from './webauthn_utils'
import type { WebAuthnChallengeData, ErrorResponse } from './types/webauthn'

document.addEventListener('DOMContentLoaded', () => {
  const addPasskeyBtn = document.getElementById('add-passkey-btn')
  const modal = document.getElementById('passkey-modal')
  const nameInput = document.getElementById('passkey-name-input') as HTMLInputElement | null
  const confirmBtn = document.getElementById('confirm-add-passkey') as HTMLButtonElement | null
  const cancelBtn = document.getElementById('cancel-add-passkey')
  const errorDiv = document.getElementById('passkey-error')

  if (!addPasskeyBtn || !modal || !nameInput || !confirmBtn || !cancelBtn || !errorDiv) return

  // Show modal when clicking "Add Passkey"
  addPasskeyBtn.addEventListener('click', () => {
    modal.classList.remove('hidden')
    nameInput.value = ''
    nameInput.focus()
    hideError()
  })

  // Hide modal when clicking cancel or background
  const hideModal = () => {
    modal.classList.add('hidden')
    nameInput.value = ''
    hideError()
  }

  cancelBtn.addEventListener('click', hideModal)
  modal.addEventListener('click', (e) => {
    if (e.target === modal || (e.target as HTMLElement).classList.contains('bg-zinc-500')) {
      hideModal()
    }
  })

  // Handle escape key
  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape' && !modal.classList.contains('hidden')) {
      hideModal()
    }
  })

  // Show error in modal
  const showError = (message: string) => {
    errorDiv.classList.remove('hidden')
    const errorText = errorDiv.querySelector('p')
    if (errorText) {
      errorText.textContent = message
    }
  }

  const hideError = () => {
    errorDiv.classList.add('hidden')
    const errorText = errorDiv.querySelector('p')
    if (errorText) {
      errorText.textContent = ''
    }
  }

  // Handle passkey registration
  const registerPasskey = async () => {
    const name = nameInput.value.trim()

    if (!name) {
      showError('Please enter a name for this passkey')
      nameInput.focus()
      return
    }

    try {
      confirmBtn.disabled = true
      confirmBtn.textContent = 'Registering...'

      // Fetch challenge from server
      const challengeResponse = await fetch('/api/webauthn/registration/challenge', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-CSRF-Token': getCsrfToken()
        }
      })

      if (!challengeResponse.ok) {
        const error: ErrorResponse = await challengeResponse.json()
        showError(error.error || 'Failed to get registration challenge')
        return
      }

      const challengeData: WebAuthnChallengeData = await challengeResponse.json()

      // Convert challenge and user ID to ArrayBuffer
      const challenge = base64urlToBuffer(challengeData.challenge)
      const userId = base64urlToBuffer(challengeData.user.id)

      const publicKeyCredentialCreationOptions: PublicKeyCredentialCreationOptions = {
        challenge,
        rp: challengeData.rp,
        user: {
          id: userId,
          name: challengeData.user.name,
          displayName: challengeData.user.displayName
        },
        pubKeyCredParams: challengeData.pubKeyCredParams as PublicKeyCredentialParameters[],
        authenticatorSelection: challengeData.authenticatorSelection,
        timeout: challengeData.timeout,
        attestation: (challengeData.attestation as AttestationConveyancePreference) || 'none'
      }

      // Hide modal before showing authenticator prompt
      modal.classList.add('hidden')

      // Create credential
      const credential = await navigator.credentials.create({
        publicKey: publicKeyCredentialCreationOptions
      }) as PublicKeyCredential

      if (!credential.response || !(credential.response instanceof AuthenticatorAttestationResponse)) {
        throw new Error('Invalid credential response')
      }

      const registrationData = {
        name: name,
        attestation: {
          id: credential.id,
          rawId: bufferToBase64url(credential.rawId),
          type: credential.type,
          response: {
            clientDataJSON: bufferToBase64url(credential.response.clientDataJSON),
            attestationObject: bufferToBase64url(credential.response.attestationObject)
          }
        }
      }

      // Send to server
      const registerResponse = await fetch('/api/webauthn/register', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-CSRF-Token': getCsrfToken()
        },
        body: JSON.stringify(registrationData)
      })

      if (registerResponse.ok) {
        // Reload page to show new passkey
        window.location.reload()
      } else {
        const error: ErrorResponse = await registerResponse.json()
        modal.classList.remove('hidden')
        showError(error.error || 'Failed to register passkey')
      }
    } catch (error) {
      console.error('Registration error:', error)

      let errorMessage = 'Failed to register passkey'
      if ((error as Error).name === 'NotAllowedError') {
        errorMessage = 'Registration was cancelled or timed out'
      } else if ((error as Error).message) {
        errorMessage = (error as Error).message
      }

      modal.classList.remove('hidden')
      showError(errorMessage)
    } finally {
      confirmBtn.disabled = false
      confirmBtn.textContent = 'Continue'
    }
  }

  // Register on button click
  confirmBtn.addEventListener('click', registerPasskey)

  // Register on Enter key
  nameInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') {
      e.preventDefault()
      registerPasskey()
    }
  })
})
