import { verifyRegistrationResponse } from '@simplewebauthn/server'
import crypto from 'crypto'
import nodemailer from 'nodemailer'
import { hashPassword, readUsers, writeUsers } from '../../utils/auth.js'
import { getWebAuthnConfig } from '../../utils/webauthn-config.js'
import { consumePreRegistration } from '../../utils/webauthn-challenges.js'
import { toBase64Url } from '../../utils/webauthn-encoding.js'
import { writeAuditLog } from '../../utils/audit-log.js'
import { assertPasswordNotPwned } from '../../utils/hibp.js'
import { getClientIp } from '../../utils/rate-limit.js'

export default defineEventHandler(async (event) => {
  const requestStart = Date.now()
  const requestOrigin = getHeader(event, 'origin')
  const userAgent = getHeader(event, 'user-agent')
  const { origin: webauthnOrigin } = getWebAuthnConfig()
  
  console.log('')
  console.log('='.repeat(80))
  console.log('[DEBUG] 🔑 ===== PASSKEY REGISTRATION REQUEST RECEIVED =====')
  console.log('='.repeat(80))
  console.log('[DEBUG] Request Details:', {
    origin: requestOrigin || 'none',
    webauthnOrigin,
    userAgent: userAgent?.substring(0, 150) || 'none',
    timestamp: new Date().toISOString(),
    method: getMethod(event),
    ip: getClientIp(event),
    url: getRequestURL(event).href,
    path: getRequestURL(event).pathname
  })
  console.log('[DEBUG] ⚠️ WICHTIG: Dieser Request sollte vom Smartphone kommen, wenn der QR-Code gescannt wurde')
  console.log('[DEBUG] ⚠️ Wenn dieser Request NICHT im Log erscheint, bedeutet das:')
  console.log('[DEBUG]   1. Das Smartphone konnte die Website nicht erreichen')
  console.log('[DEBUG]   2. Oder startRegistration auf dem Smartphone ist fehlgeschlagen')
  console.log('[DEBUG]   3. Oder die Credential-Response wurde nicht gesendet')
  console.log('='.repeat(80))
  console.log('')
  console.log('[DEBUG] User-Agent Analysis:', {
    isMobile: /Mobile|Android|iPhone|iPad/i.test(userAgent || ''),
    isChrome: /Chrome/i.test(userAgent || ''),
    isSafari: /Safari/i.test(userAgent || '') && !/Chrome/i.test(userAgent || ''),
    isFirefox: /Firefox/i.test(userAgent || ''),
    fullUserAgent: userAgent
  })

  // CORS-Header für Cross-Device Authentication
  // OPTIONS-Requests werden von .options.js behandelt
  const allowedOrigin = requestOrigin || webauthnOrigin
  if (allowedOrigin) {
    setHeader(event, 'Access-Control-Allow-Origin', allowedOrigin)
    setHeader(event, 'Access-Control-Allow-Credentials', 'true')
    setHeader(event, 'Access-Control-Allow-Methods', 'POST, OPTIONS')
    setHeader(event, 'Access-Control-Allow-Headers', 'Content-Type, Authorization, Origin, X-Requested-With')
    console.log('[DEBUG] CORS headers set for POST', { 
      origin: allowedOrigin,
      requestOrigin,
      webauthnOrigin
    })
  }

  const body = await readBody(event)
  const registrationId = String(body?.registrationId || '')
  const response = body?.credential
  const password = body?.password ? String(body.password) : ''

  console.log('[DEBUG] Request body parsed', {
    hasRegistrationId: !!registrationId,
    registrationId: registrationId.substring(0, 10) + '...',
    hasCredential: !!response,
    credentialId: response?.id,
    hasPassword: !!password
  })

  if (!registrationId || !response) {
    console.error('[DEBUG] Validation failed: missing registrationId or credential')
    throw createError({ statusCode: 400, statusMessage: 'Ungültige Anfrage' })
  }

  const pre = consumePreRegistration(registrationId)
  if (!pre) {
    console.error('[DEBUG] Pre-registration not found or expired', { registrationId })
    throw createError({ statusCode: 400, statusMessage: 'Registrierungs-Session abgelaufen. Bitte erneut versuchen.' })
  }

  const { challenge, userId, name, email, phone } = pre
  console.log('[DEBUG] Pre-registration found', {
    userId,
    email: email.substring(0, 10) + '...',
    hasChallenge: !!challenge
  })

  const users = await readUsers()
  if (users.some(u => String(u.email || '').toLowerCase() === String(email).toLowerCase())) {
    console.error('[DEBUG] User already exists', { email })
    throw createError({ statusCode: 409, message: 'Ein Benutzer mit dieser E-Mail-Adresse existiert bereits' })
  }

  const { origin, rpId, requireUV } = getWebAuthnConfig()
  
  // Debug: Prüfe die tatsächliche Origin aus der Response
  const clientData = response?.response?.clientDataJSON
  let actualOrigin = null
  if (clientData) {
    try {
      const decoded = Buffer.from(clientData, 'base64').toString('utf-8')
      const parsed = JSON.parse(decoded)
      actualOrigin = parsed.origin
      console.log('[DEBUG] Parsed clientDataJSON', {
        origin: parsed.origin,
        type: parsed.type,
        challenge: parsed.challenge ? 'present' : 'missing'
      })
    } catch (e) {
      console.warn('[DEBUG] Could not parse clientDataJSON:', e)
    }
  }
  
  console.log('[DEBUG] WebAuthn config for verification', {
    expectedOrigin: origin,
    expectedOriginType: typeof origin,
    expectedOriginLength: origin?.length,
    actualOriginFromResponse: actualOrigin,
    rpId,
    requireUV,
    originMatch: origin === actualOrigin,
    webauthnOriginEnv: process.env.WEBAUTHN_ORIGIN,
    baseUrlEnv: process.env.NUXT_PUBLIC_BASE_URL
  })
  
  // WICHTIG: Sicherstellen, dass die Origin KEINEN Port hat
  if (origin && origin.includes(':3100')) {
    console.error('[DEBUG] ERROR: expectedOrigin contains port 3100! This will cause verification to fail.')
    console.error('[DEBUG] Fix: Set WEBAUTHN_ORIGIN=https://harheimertc.tsschulz.de (without port) in .env')
    throw createError({ 
      statusCode: 500, 
      statusMessage: 'WebAuthn-Konfiguration fehlerhaft: Origin enthält Port 3100. Bitte WEBAUTHN_ORIGIN in .env korrigieren.' 
    })
  }

  console.log('[DEBUG] Verifying registration response...')
  console.log('[DEBUG] Verification parameters', {
    expectedOrigin: origin,
    expectedRPID: rpId,
    hasChallenge: !!challenge,
    challengeLength: challenge?.length,
    hasResponse: !!response,
    responseId: response?.id
  })
  
  const verifyStart = Date.now()
  
  let verification
  try {
    verification = await verifyRegistrationResponse({
      response,
      expectedChallenge: challenge,
      expectedOrigin: origin,
      expectedRPID: rpId,
      requireUserVerification: requireUV
    })
  } catch (verifyError) {
    const verifyDuration = Date.now() - verifyStart
    console.error('[DEBUG] Verification error:', { verifyDurationMs: verifyDuration,
      error: verifyError,
      message: verifyError?.message,
      cause: verifyError?.cause?.message,
      expectedOrigin: origin,
      actualOriginFromResponse: actualOrigin,
      stack: verifyError?.stack
    })
    throw verifyError
  }

  const verifyDuration = Date.now() - verifyStart
  const { verified, registrationInfo } = verification
    
    console.log('[DEBUG] Verification completed', { verifyDurationMs: verifyDuration,
      verified,
      hasRegistrationInfo: !!registrationInfo,
      credentialId: registrationInfo?.credentialID ? 'present' : 'missing',
      deviceType: registrationInfo?.credentialDeviceType,
      backedUp: registrationInfo?.credentialBackedUp
    })
    
    if (!verified || !registrationInfo) {
      console.error('[DEBUG] Verification failed', {
        verified,
        hasRegistrationInfo: !!registrationInfo
      })
      await writeAuditLog('auth.passkey.prereg.failed', { email })
      throw createError({ statusCode: 400, statusMessage: 'Passkey-Registrierung fehlgeschlagen' })
    }

  const {
    credentialID,
    credentialPublicKey,
    counter,
    credentialDeviceType,
    credentialBackedUp
  } = registrationInfo

  const credentialId = toBase64Url(credentialID)
  const publicKey = toBase64Url(credentialPublicKey)

  // Optional: Passwort als Fallback (z.B. Firefox/Linux) erlauben
  let hashedPassword
  if (password && password.trim().length > 0) {
    if (password.length < 8) {
      throw createError({ statusCode: 400, message: 'Das Passwort muss mindestens 8 Zeichen lang sein' })
    }
    await assertPasswordNotPwned(password)
    hashedPassword = await hashPassword(password)
  } else {
    // Kein Passwort gesetzt: random Hash, damit bestehende Code-Pfade (verifyPassword) konsistent bleiben.
    hashedPassword = await hashPassword(crypto.randomBytes(32).toString('hex'))
  }

  const newUser = {
    id: String(userId),
    email: String(email).toLowerCase(),
    password: hashedPassword,
    name,
    phone: phone || '',
    role: 'mitglied',
    active: false,
    created: new Date().toISOString(),
    lastLogin: null,
    passkeys: [
      {
        id: `${Date.now()}`,
        credentialId,
        publicKey,
        counter: Number(counter) || 0,
        transports: Array.isArray(response.transports) ? response.transports : undefined,
        deviceType: credentialDeviceType,
        backedUp: !!credentialBackedUp,
        createdAt: new Date().toISOString(),
        lastUsedAt: null,
        name: 'Passkey'
      }
    ]
  }

  users.push(newUser)
  await writeUsers(users)
  
  const totalDuration = Date.now() - requestStart
  console.log('[DEBUG] User created successfully', { totalDurationMs: totalDuration,
    userId: newUser.id,
    email: newUser.email.substring(0, 10) + '...',
    hasPasskey: newUser.passkeys?.length > 0,
    hasPassword: !!newUser.password
  })

  await writeAuditLog('auth.passkey.prereg.success', { email, userId: newUser.id })

  // Send notification emails (same behavior as password registration)
  try {
    const smtpUser = process.env.SMTP_USER
    const smtpPass = process.env.SMTP_PASS

    if (smtpUser && smtpPass) {
      const transporter = nodemailer.createTransport({
        host: process.env.SMTP_HOST || 'smtp.gmail.com',
        port: process.env.SMTP_PORT || 587,
        secure: false,
        auth: { user: smtpUser, pass: smtpPass }
      })

      await transporter.sendMail({
        from: process.env.SMTP_FROM || 'noreply@harheimertc.de',
        to: process.env.SMTP_ADMIN || 'j.dichmann@gmx.de',
        subject: 'Neue Registrierung (Passkey) - Harheimer TC',
        html: `
          <h2>Neue Registrierung (Passkey)</h2>
          <p>Ein neuer Benutzer hat sich registriert und wartet auf Freigabe:</p>
          <ul>
            <li><strong>Name:</strong> ${name}</li>
            <li><strong>E-Mail:</strong> ${email}</li>
            <li><strong>Telefon:</strong> ${phone || 'Nicht angegeben'}</li>
            <li><strong>Login:</strong> Passkey${password ? ' + Passwort (Fallback)' : ' (ohne Passwort)'}</li>
          </ul>
          <p>Bitte prüfen Sie die Registrierung im CMS.</p>
        `
      })

      await transporter.sendMail({
        from: process.env.SMTP_FROM || 'noreply@harheimertc.de',
        to: email,
        subject: 'Registrierung erhalten - Harheimer TC',
        html: `
          <h2>Registrierung erhalten</h2>
          <p>Hallo ${name},</p>
          <p>vielen Dank für Ihre Registrierung beim Harheimer TC!</p>
          <p>Ihre Anfrage wird vom Vorstand geprüft. Sie erhalten eine E-Mail, sobald Ihr Zugang freigeschaltet wurde.</p>
          <br>
          <p>Mit sportlichen Grüßen,<br>Ihr Harheimer TC</p>
        `
      })
    }
  } catch (emailError) {
    console.error('E-Mail-Versand fehlgeschlagen:', emailError)
  }

  return {
    success: true,
    message: 'Registrierung erfolgreich. Sie erhalten eine E-Mail, sobald Ihr Zugang freigeschaltet wurde.'
  }
})

