import React, { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { cycleAppLanguage, getNextLanguage } from '../utils/i18nLanguages.js'
import {
  registerUser,
  loginUser,
  completeLoginWithRecovery,
  setLocalPin,
  hasLocalPin,
  decryptWithLocalPin,
  getActiveMasterKey,
  getKnownUsernames,
  forgetUsername,
  hasUnlockedLocalSession,
  logoutUser,
  resolveRestoreUsername
} from '../services/auth.js'
import { KeyRound, ShieldAlert, Languages, HelpCircle, UserRound, X } from 'lucide-react'
import RegistrationDisclaimer from './RegistrationDisclaimer.tsx'
import DisclaimerModal from './DisclaimerModal.tsx'
import BetaBadge from './BetaBadge.tsx'
import {
  isPasskeyCompatibleLocation,
  localizeWebAuthnError,
  toPasskeyCompatibleUrl
} from '../utils/passkeyHost.ts'

interface AuthOnboardingProps {
  onAuthenticated: () => void
  onOpenDemo?: () => void
  /** Server session cookie is valid but the in-memory master key was lost (e.g. after reload). */
  restoreSession?: boolean
}

export default function AuthOnboarding({
  onAuthenticated,
  onOpenDemo,
  restoreSession = false
}: AuthOnboardingProps) {
  const { t, i18n } = useTranslation()
  const [username, setUsername] = useState('')
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)

  // Accounts that have already authenticated on this device. Used to offer a
  // one-click login without re-typing the username.
  const [knownUsers, setKnownUsers] = useState<string[]>(() => getKnownUsernames())
  
  // Registration recovery phrase flow
  const [recoveryPhrase, setRecoveryPhrase] = useState<string | null>(null)
  const [copied, setCopied] = useState(false)

  // Login recovery phrase fallback flow
  const [showRecoveryFallback, setShowRecoveryFallback] = useState(false)
  const [recoveryInput, setRecoveryInput] = useState('')
  const [encryptedPayloads, setEncryptedPayloads] = useState<any>(null)

  // PIN setup flow state
  const [showPinSetup, setShowPinSetup] = useState(false)
  const [pinInput, setPinInput] = useState('')
  const [pinSetupUsername, setPinSetupUsername] = useState('')

  // PIN login fallback flow state
  const [showPinLogin, setShowPinLogin] = useState(false)
  const [pinLoginInput, setPinLoginInput] = useState('')

  const [isNewRegistration, setIsNewRegistration] = useState(false)
  const [showDisclaimer, setShowDisclaimer] = useState(false)
  const [showHelp, setShowHelp] = useState(false)
  const [showStandardLogin, setShowStandardLogin] = useState(false)
  const autoUnlockAttempted = useRef(false)

  const isRestoreFlow = restoreSession && !showStandardLogin
  const passkeyHostOk = isPasskeyCompatibleLocation()
  const passkeyCompatibleUrl = passkeyHostOk ? null : toPasskeyCompatibleUrl(window.location.href)

  const formatAuthError = (message: string) =>
    localizeWebAuthnError(message, {
      invalidHost: t('auth.error_invalid_host'),
      cancelled: t('auth.error_passkey_cancelled'),
      invalidRpId: t('auth.error_invalid_rp_id')
    })

  const finishAuth = () => {
    if (isNewRegistration) {
      setShowDisclaimer(true)
      return
    }
    onAuthenticated()
  }

  const handleDisclaimerAccept = () => {
    setIsNewRegistration(false)
    setShowDisclaimer(false)
    onAuthenticated()
  }

  const handleRegister = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!username.trim()) return

    setLoading(true)
    setError(null)
    try {
      const result = await registerUser(username.trim())
      if (result.verified) {
        setIsNewRegistration(true)
        setRecoveryPhrase(result.recoveryPhrase)
      }
    } catch (err: any) {
      setError(formatAuthError(err.message || 'Registration failed'))
    } finally {
      setLoading(false)
    }
  }

  const handleLogin = async (explicitUsername?: string) => {
    setLoading(true)
    setError(null)
    try {
      // Pass the username when available so the server returns a concrete
      // allowCredentials list. A usernameless (discoverable) assertion fails on
      // some platform authenticators (e.g. Windows Hello); giving the explicit
      // credential id makes those work. Priority: an explicitly clicked account
      // > a typed name > the single remembered account > usernameless discovery.
      const remembered = getKnownUsernames()
      const target =
        explicitUsername ||
        username.trim() ||
        (remembered.length === 1 ? remembered[0] : undefined)
      const result = await loginUser(target)
      if (result.verified) {
        if (result.prfSuccess) {
          // Biometric E2E decryption succeeded
          onAuthenticated()
        } else {
          // Biometrics succeeded but PRF key wasn't supported/available, fall back to PIN or recovery phrase
          setEncryptedPayloads(result.encryptedPayloads)
          const resolvedUser = result.username || result.encryptedPayloads?.username || ''
          if (resolvedUser) {
            setUsername(resolvedUser)
          }
          if (resolvedUser && hasLocalPin(resolvedUser)) {
            setShowPinLogin(true)
          } else {
            setShowRecoveryFallback(true)
          }
        }
      }
    } catch (err: any) {
      setError(formatAuthError(err.message || 'Login failed'))
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    if (!isRestoreFlow || autoUnlockAttempted.current) return

    const user = resolveRestoreUsername()
    if (user && hasLocalPin(user)) {
      autoUnlockAttempted.current = true
      setUsername(user)
      setShowPinLogin(true)
      return
    }

    if (user && passkeyHostOk) {
      autoUnlockAttempted.current = true
      void handleLogin(user)
    }
  }, [isRestoreFlow, passkeyHostOk])

  const handleRecoverySubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!recoveryInput.trim() || !encryptedPayloads) return

    setLoading(true)
    setError(null)
    try {
      const resolvedUser = username.trim() || encryptedPayloads.username
      const success = await completeLoginWithRecovery(resolvedUser, recoveryInput.trim(), encryptedPayloads)
      if (success) {
        // Offer PIN setup to prevent future recovery phrase entries on this device
        setPinSetupUsername(resolvedUser)
        setShowRecoveryFallback(false)
        setShowPinSetup(true)
      } else {
        setError(t('auth.error_incorrect_recovery'))
      }
    } catch (err: any) {
      setError(t('auth.error_decryption_failed'))
    } finally {
      setLoading(false)
    }
  }

  const handleConfirmRecovery = () => {
    setPinSetupUsername(username.trim() || encryptedPayloads?.username || '')
    // Clear the recovery phrase so the PIN-setup screen can render: the
    // `recoveryPhrase` branch is evaluated before `showPinSetup`, so leaving it
    // set would keep the user stuck on the recovery-phrase screen.
    setRecoveryPhrase(null)
    setShowPinSetup(true)
  }

  const handlePinSetupSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!pinInput.trim() || pinInput.length < 4) {
      setError(t('auth.pin_length_error', 'PIN must be at least 4 digits'))
      return
    }
    setLoading(true)
    setError(null)
    try {
      const activeKey = getActiveMasterKey()
      if (activeKey) {
        await setLocalPin(pinInput.trim(), pinSetupUsername, activeKey)
        finishAuth()
      } else {
        setError('No active master key found')
      }
    } catch (err: any) {
      setError(err.message || 'Failed to save PIN')
    } finally {
      setLoading(false)
    }
  }

  const handlePinLoginSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!pinLoginInput.trim() || loading) return

    const resolvedUser =
      username.trim() ||
      encryptedPayloads?.username ||
      localStorage.getItem('active_username') ||
      ''
    if (!resolvedUser) {
      setError(t('auth.error_session_incomplete'))
      return
    }

    setLoading(true)
    setError(null)
    try {
      const key = await decryptWithLocalPin(pinLoginInput.trim(), resolvedUser)
      if (!key) {
        setError(t('auth.error_incorrect_pin'))
        return
      }
      if (!hasUnlockedLocalSession()) {
        setError(t('auth.error_session_incomplete'))
        return
      }
      setShowPinLogin(false)
      onAuthenticated()
    } catch {
      setError(t('auth.error_incorrect_pin'))
    } finally {
      setLoading(false)
    }
  }

  const handleForgetUser = (name: string) => {
    forgetUsername(name)
    setKnownUsers(getKnownUsernames())
  }

  const toggleLanguage = () => {
    cycleAppLanguage(i18n)
  }

  const copyToClipboard = () => {
    if (recoveryPhrase) {
      navigator.clipboard.writeText(recoveryPhrase)
      setCopied(true)
      setTimeout(() => setCopied(false), 2000)
    }
  }

  // Render 0: Registration disclaimer (new accounts only, before app onboarding)
  if (showDisclaimer) {
    return <RegistrationDisclaimer variant="accept" onDismiss={handleDisclaimerAccept} />
  }

  // Render 1: Display new registration recovery phrase
  if (recoveryPhrase) {
    return (
      <div className="auth-card glass">
        <div className="auth-header">
          <ShieldAlert className="auth-icon warn" size={48} />
          <h2>{t('auth.recovery_title')}</h2>
        </div>
        <p className="recovery-warning">{t('auth.recovery_warning')}</p>
        
        <div className="phrase-grid">
          {recoveryPhrase.split(" ").map((word, idx) => (
            <div key={idx} className="phrase-word">
              <span className="word-num">{idx + 1}</span> {word}
            </div>
          ))}
        </div>

        <div className="auth-actions">
          <button className="btn secondary" onClick={copyToClipboard}>
            {copied ? t('auth.copied') : t('auth.copy_phrase')}
          </button>
          <button className="btn primary" onClick={handleConfirmRecovery}>
            {t('auth.confirm_recovery')}
          </button>
        </div>
      </div>
    )
  }

  // Render 4: PIN setup screen
  if (showPinSetup) {
    return (
      <div className="auth-card glass">
        <div className="auth-header">
          <KeyRound className="auth-icon accent" size={48} />
          <h2>{t('auth.setup_pin_title')}</h2>
        </div>
        <p className="recovery-warning">
          {t('auth.setup_pin_warning')}
        </p>

        <form onSubmit={handlePinSetupSubmit} className="auth-form">
          <div className="input-group">
            <label className="input-label" style={{ display: 'block', marginBottom: '8px', color: '#94a3b8' }}>
              {t('auth.pin_label')}
            </label>
            <input
              type="password"
              name="new-pin"
              inputMode="numeric"
              pattern="[0-9]*"
              maxLength={8}
              className="input-text"
              placeholder={t('auth.pin_placeholder')}
              value={pinInput}
              onChange={(e) => setPinInput(e.target.value.replace(/\D/g, ''))}
              disabled={loading}
              required
              autoComplete="new-password"
              style={{ width: '100%', padding: '12px', boxSizing: 'border-box' }}
            />
          </div>

          {error && <div className="auth-error" style={{ color: '#ef4444', fontSize: '14px', marginTop: '8px' }}>{error}</div>}

          <div className="auth-actions" style={{ marginTop: '20px' }}>
            <button
              type="button"
              className="btn secondary"
              onClick={finishAuth}
              disabled={loading}
            >
              {t('auth.skip_pin')}
            </button>
            <button type="submit" className="btn primary" disabled={loading || pinInput.length < 4}>
              {loading ? t('auth.processing') : t('auth.save_pin')}
            </button>
          </div>
        </form>
      </div>
    )
  }

  // Render 5: PIN login screen
  if (showPinLogin) {
    return (
      <div className="auth-card glass">
        <div className="auth-header">
          <KeyRound className="auth-icon accent" size={48} />
          <h2>{isRestoreFlow ? t('auth.restore_title') : t('auth.enter_pin_title')}</h2>
        </div>
        <p className="recovery-warning">
          {isRestoreFlow ? t('auth.restore_pin_warning') : t('auth.enter_pin_warning')}
        </p>

        <form onSubmit={handlePinLoginSubmit} className="auth-form">
          <div className="input-group">
            <input
              type="password"
              name="pin"
              inputMode="numeric"
              pattern="[0-9]*"
              maxLength={8}
              className="input-text"
              placeholder={t('auth.enter_pin_placeholder')}
              value={pinLoginInput}
              onChange={(e) => setPinLoginInput(e.target.value.replace(/\D/g, ''))}
              disabled={loading}
              required
              autoComplete="current-password"
              style={{ width: '100%', padding: '12px', boxSizing: 'border-box' }}
            />
          </div>

          {error && <div className="auth-error" style={{ color: '#ef4444', fontSize: '14px', marginTop: '8px' }}>{error}</div>}

          <div className="auth-actions" style={{ flexDirection: 'column', gap: '10px', marginTop: '20px' }}>
            <button type="submit" className="btn primary" disabled={loading} style={{ width: '100%' }}>
              {loading ? t('auth.decrypting') : t('auth.decrypt_with_pin')}
            </button>
            
            <button
              type="button"
              className="btn secondary"
              onClick={() => {
                setShowPinLogin(false)
                setShowRecoveryFallback(true)
                setError(null)
              }}
              disabled={loading}
              style={{ width: '100%' }}
            >
              {t('auth.use_recovery_instead')}
            </button>

            <button
              type="button"
              className="btn secondary"
              onClick={() => {
                if (isRestoreFlow) {
                  setShowPinLogin(false)
                  setPinLoginInput('')
                  setError(null)
                  return
                }
                void (async () => {
                  setShowPinLogin(false)
                  setPinLoginInput('')
                  setEncryptedPayloads(null)
                  setError(null)
                  await logoutUser()
                })()
              }}
              disabled={loading}
              style={{ width: '100%' }}
            >
              {t('auth.back')}
            </button>
          </div>
        </form>
      </div>
    )
  }

  // Render 2: Ask for recovery phrase fallback if biometric PRF fails
  if (showRecoveryFallback) {
    return (
      <div className="auth-card glass">
        <div className="auth-header">
          <KeyRound className="auth-icon accent" size={48} />
          <h2>{t('auth.enter_recovery')}</h2>
        </div>
        <p className="recovery-warning">
          {t('auth.recovery_fallback_warning')}
        </p>

        <form onSubmit={handleRecoverySubmit} className="auth-form" autoComplete="on">
          {(username.trim() || encryptedPayloads?.username) && (
            <input
              type="text"
              name="username"
              autoComplete="username"
              value={username.trim() || encryptedPayloads?.username || ''}
              readOnly
              tabIndex={-1}
              aria-hidden="true"
              style={{ position: 'absolute', width: 0, height: 0, opacity: 0, pointerEvents: 'none' }}
            />
          )}
          <div className="input-group">
            <label htmlFor="recovery-key" className="input-label" style={{ display: 'block', marginBottom: '8px', color: '#94a3b8' }}>
              {t('auth.enter_recovery')}
            </label>
            <input
              id="recovery-key"
              name="recovery-key"
              type="password"
              className="input-text"
              placeholder={t('auth.recovery_placeholder')}
              value={recoveryInput}
              onChange={(e) => setRecoveryInput(e.target.value)}
              disabled={loading}
              required
              autoComplete="current-password"
              style={{ width: '100%', padding: '12px', boxSizing: 'border-box' }}
            />
          </div>

          {error && <div className="auth-error">{error}</div>}

          <div className="auth-actions">
            <button
              type="button"
              className="btn secondary"
              onClick={() => setShowRecoveryFallback(false)}
              disabled={loading}
            >
              {t('auth.back')}
            </button>
            <button type="submit" className="btn primary" disabled={loading}>
              {loading ? t('auth.decrypting') : t('auth.decrypt_logbook')}
            </button>
          </div>
        </form>
      </div>
    )
  }

  // Render: Session restore (active server cookie, master key lost after reload)
  if (isRestoreFlow) {
    const restoreUser = resolveRestoreUsername()
    const restoreKnownUsers = getKnownUsernames()

    return (
      <div className="auth-card glass">
        <div className="auth-header">
          <KeyRound className="auth-icon accent" size={48} />
          <h2>{t('auth.restore_title')}</h2>
        </div>
        <p className="recovery-warning">{t('auth.restore_subtitle')}</p>

        {loading && (
          <p className="dashboard-status-msg" style={{ marginTop: '12px' }}>
            {t('auth.restore_unlocking')}
          </p>
        )}

        {error && <div className="auth-error">{error}</div>}

        {!loading && (
          <div className="auth-actions" style={{ flexDirection: 'column', gap: '10px', marginTop: '16px' }}>
            {restoreUser && passkeyHostOk && (
              <button
                type="button"
                className="btn primary"
                onClick={() => handleLogin(restoreUser)}
                style={{ width: '100%' }}
              >
                {t('auth.restore_with_passkey', { name: restoreUser })}
              </button>
            )}

            {restoreUser && hasLocalPin(restoreUser) && (
              <button
                type="button"
                className="btn secondary"
                onClick={() => {
                  setUsername(restoreUser)
                  setShowPinLogin(true)
                }}
                style={{ width: '100%' }}
              >
                {t('auth.restore_with_pin')}
              </button>
            )}

            {restoreKnownUsers.length > 1 && (
              <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', width: '100%' }}>
                <span style={{ fontSize: '12px', color: '#64748b', textTransform: 'uppercase' }}>
                  {t('auth.quick_login')}
                </span>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', width: '100%' }}>
                  {restoreKnownUsers.map((name) => (
                    <button
                      key={name}
                      type="button"
                      onClick={() => {
                        if (hasLocalPin(name)) {
                          setUsername(name)
                          setShowPinLogin(true)
                        } else {
                          void handleLogin(name)
                        }
                      }}
                      disabled={loading}
                      className="btn secondary"
                      style={{ display: 'flex', alignItems: 'center', gap: '6px' }}
                    >
                      <UserRound size={16} />
                      {name}
                    </button>
                  ))}
                </div>
              </div>
            )}

            <button
              type="button"
              className="btn secondary"
              onClick={() => {
                setShowStandardLogin(true)
                setError(null)
              }}
              style={{ width: '100%' }}
            >
              {t('auth.restore_other_account')}
            </button>
          </div>
        )}
      </div>
    )
  }

  // Render 3: Standard Login / Registration options form
  return (
    <>
    <div className="auth-card glass">
      <div className="auth-brand">
        <img src="/logo.png" alt="Kapteins Daagbok" className="auth-logo-img" />
        <div className="auth-brand-title-row">
          <h1>{t('app.name')}</h1>
          <BetaBadge />
        </div>
        <p className="tagline">{t('auth.tagline')}</p>
      </div>

      <div className="auth-form" style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: '20px' }}>
        {!passkeyHostOk && passkeyCompatibleUrl && (
          <div className="auth-error" role="alert">
            <p style={{ margin: '0 0 8px' }}>{t('auth.error_invalid_host')}</p>
            <a href={passkeyCompatibleUrl} className="btn secondary" style={{ display: 'inline-block', textDecoration: 'none' }}>
              {t('auth.use_localhost_link')}
            </a>
          </div>
        )}

        {/* Prominent Login button */}
        <button
          type="button"
          className="btn primary"
          onClick={() => handleLogin()}
          disabled={loading || !passkeyHostOk}
          style={{ width: '100%', padding: '16px' }}
        >
          {loading
            ? t('auth.processing')
            : knownUsers.length === 1
              ? t('auth.login_as', { name: knownUsers[0] })
              : t('auth.login')}
        </button>

        {/* Single remembered account: the main button already logs in as them,
            so just offer a way to forget it (e.g. on a shared device). */}
        {knownUsers.length === 1 && (
          <button
            type="button"
            onClick={() => handleForgetUser(knownUsers[0])}
            disabled={loading}
            style={{
              background: 'transparent',
              border: 'none',
              color: '#64748b',
              cursor: 'pointer',
              fontSize: '13px',
              textDecoration: 'underline',
              alignSelf: 'center',
              padding: 0
            }}
          >
            {t('auth.not_user', { name: knownUsers[0] })}
          </button>
        )}

        {/* Quick-login chips for accounts remembered on this device. Each one
            logs in with its concrete credential, so no username typing needed. */}
        {knownUsers.length > 1 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', width: '100%' }}>
            <span style={{ fontSize: '12px', color: '#64748b', textTransform: 'uppercase' }}>
              {t('auth.quick_login')}
            </span>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', width: '100%' }}>
              {knownUsers.map((name) => (
                <div
                  key={name}
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: '4px',
                    background: 'rgba(255,255,255,0.06)',
                    border: '1px solid rgba(255,255,255,0.1)',
                    borderRadius: '999px',
                    padding: '4px 4px 4px 12px'
                  }}
                >
                  <button
                    type="button"
                    onClick={() => handleLogin(name)}
                    disabled={loading}
                    style={{
                      display: 'flex',
                      alignItems: 'center',
                      gap: '6px',
                      background: 'transparent',
                      border: 'none',
                      color: '#e2e8f0',
                      cursor: 'pointer',
                      fontSize: '14px',
                      padding: 0
                    }}
                  >
                    <UserRound size={16} />
                    {name}
                  </button>
                  <button
                    type="button"
                    onClick={() => handleForgetUser(name)}
                    disabled={loading}
                    title={t('auth.forget_account')}
                    aria-label={t('auth.forget_account')}
                    style={{
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                      width: '22px',
                      height: '22px',
                      background: 'transparent',
                      border: 'none',
                      color: '#94a3b8',
                      cursor: 'pointer',
                      borderRadius: '50%'
                    }}
                  >
                    <X size={14} />
                  </button>
                </div>
              ))}
            </div>
          </div>
        )}

        {/* Separator */}
        <div style={{ display: 'flex', alignItems: 'center', margin: '10px 0', width: '100%' }}>
          <div style={{ flex: 1, height: '1px', background: 'rgba(255,255,255,0.1)' }}></div>
          <span style={{ padding: '0 10px', fontSize: '12px', color: '#64748b', textTransform: 'uppercase' }}>{t('auth.or_register')}</span>
          <div style={{ flex: 1, height: '1px', background: 'rgba(255,255,255,0.1)' }}></div>
        </div>

        <button
          type="button"
          className="btn secondary"
          onClick={() => onOpenDemo?.()}
          disabled={loading}
          style={{ width: '100%' }}
        >
          {t('auth.explore_demo')}
        </button>

        {/* Registration form */}
        <form onSubmit={handleRegister} style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '100%' }}>
          <div className="input-group">
            <input
              type="text"
              className="input-text"
              placeholder={t('auth.username_placeholder')}
              value={username}
              onChange={(e) => setUsername(e.target.value)}
              disabled={loading}
              required
            />
          </div>

          <button
            type="submit"
            className="btn secondary"
            disabled={loading || !username.trim() || !passkeyHostOk}
            style={{ width: '100%' }}
          >
            {t('auth.register')}
          </button>
        </form>

        {error && <div className="auth-error">{error}</div>}
      </div>

      <div className="auth-footer">
        <button type="button" className="btn-icon-text" onClick={toggleLanguage}>
          <Languages size={18} />
          {t(`languages.${getNextLanguage(i18n.language)}`)}
        </button>
        <button
          type="button"
          className="btn-icon-text link-sec"
          onClick={() => setShowHelp(true)}
          title={t('disclaimer.button_title')}
          aria-label={t('disclaimer.button_title')}
        >
          <HelpCircle size={18} />
          {t('auth.help')}
        </button>
      </div>
    </div>
    <DisclaimerModal open={showHelp} onClose={() => setShowHelp(false)} />
    </>
  )
}
