<template>
  <Transition name="modal-fade">
    <div v-if="isOpen" class="auth-modal-overlay" @click.self="closeModal">
      <div class="auth-modal-container">
        <div class="auth-modal-content">
          <!-- Close Button — matches film detail modal -->
          <button @click="closeModal" class="auth-close-btn">
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>

          <!-- ═══ NORMAL AUTH VIEW ═══ -->
          <template v-if="sovereignPhase === 'normal'">
            <!-- ─── REMOTE SIGNER QR PHASE (desktop) ─── -->
            <template v-if="remoteSignerPhase === 'qr'">
              <div class="text-center">
                <button
                  @click="handleRemoteSignerBack"
                  class="flex items-center gap-2 text-white/60 hover:text-white transition-colors mb-6 w-full justify-start"
                >
                  <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
                  </svg>
                  Back
                </button>

                <div v-if="errorMessage" class="mb-4 p-3 rounded-lg bg-red-500/20 border border-red-500/30 text-red-400 text-sm text-left">
                  {{ errorMessage }}
                </div>

                <h2 class="text-2xl font-bold text-white mb-2">Remote Signer</h2>
                <p class="text-white/50 text-sm mb-6">Scan the QR code with your phone to sign in</p>

                <!-- QR Code -->
                <div class="bg-white rounded-2xl p-4 inline-block mb-5">
                  <img v-if="remoteSignerQrDataUrl" :src="remoteSignerQrDataUrl" alt="Nostr Connect QR" class="w-56 h-56" />
                  <div v-else class="w-56 h-56 flex items-center justify-center text-gray-400">
                    Generating QR...
                  </div>
                </div>

                <p v-if="nostrConnectLoading" class="text-sm text-white/70 animate-pulse mb-4">
                  Waiting for signer...
                </p>

                <!-- Copy URI -->
                <button
                  @click="copyRemoteSignerUri"
                  class="w-full bg-white/10 hover:bg-white/15 text-white rounded-xl px-4 py-3 text-sm font-medium transition-colors flex items-center justify-center gap-2 mb-4"
                >
                  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
                  </svg>
                  {{ remoteSignerCopyText }}
                </button>

                <p class="text-xs text-white/40">
                  Use Primal, Amber, or any Nostr Connect signer app
                </p>
              </div>
            </template>

            <!-- ─── AUTH OPTIONS (idle) ─── -->
            <template v-else>
            <!-- Header -->
            <div class="text-center mb-8">
              <h2 class="text-3xl font-bold text-white">
                {{ mode === 'login' ? 'Welcome Back' : 'Join IndeeHub' }}
              </h2>
            </div>

            <!-- Error Message -->
            <div v-if="errorMessage" class="mb-4 p-3 rounded-lg bg-red-500/20 border border-red-500/30 text-red-400 text-sm">
              {{ errorMessage }}
            </div>

            <!-- Auth Form — first click triggers sovereign flow; after dismiss, form is functional -->
            <form class="space-y-4" :class="{ 'sovereign-trap': !sovereignDismissed }" @click.capture="triggerSovereignFlow" @submit.prevent>
              <div class="form-group">
                <label class="block text-white/80 text-sm font-medium mb-2">Email</label>
                <input
                  v-if="sovereignDismissed"
                  type="email"
                  class="auth-input"
                  placeholder="you@example.com"
                />
                <div v-else class="auth-input pointer-events-none select-none text-white/30">you@example.com</div>
              </div>
              <div class="form-group">
                <label class="block text-white/80 text-sm font-medium mb-2">Password</label>
                <input
                  v-if="sovereignDismissed"
                  type="password"
                  class="auth-input"
                  :placeholder="mode === 'register' ? 'Create a password' : 'Enter your password'"
                />
                <div v-else class="auth-input pointer-events-none select-none text-white/30">{{ mode === 'register' ? 'Create a password' : 'Enter your password' }}</div>
              </div>
              <div v-if="mode === 'login'" class="text-right">
                <span class="text-sm text-white/60">Forgot password?</span>
              </div>
              <button type="submit" class="hero-play-button w-full flex items-center justify-center mb-4">
                <span>{{ mode === 'register' ? 'Create Account' : 'Sign In' }}</span>
              </button>
            </form>

            <!-- Remote Signer — desktop: QR phase; mobile: direct link -->
            <div class="mt-4 space-y-2">
              <template v-if="isDesktop">
                <button
                  @click="handleRemoteSignerClick"
                  :disabled="isLoading"
                  class="nostr-login-button w-full flex items-center justify-center gap-2"
                >
                  <img
                    src="@/assets/images/primal-icon.svg"
                    alt="Remote Signer"
                    class="w-5 h-5 shrink-0"
                  />
                  Remote Signer
                </button>
              </template>
              <template v-else>
                <button
                  v-if="!popupBlockedUri"
                  @click="handleNostrConnectLogin"
                  :disabled="isLoading"
                  class="nostr-login-button w-full flex items-center justify-center gap-2"
                >
                  <svg v-if="nostrConnectLoading" class="w-5 h-5 shrink-0 animate-spin" fill="none" viewBox="0 0 24 24">
                    <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
                    <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
                  </svg>
                  <img v-else src="@/assets/images/primal-icon.svg" alt="Primal" class="w-5 h-5 shrink-0" />
                  {{ nostrConnectLoading ? 'Waiting...' : 'Remote Signer' }}
                </button>
                <template v-else>
                  <p class="text-sm text-white/70 text-center">
                    Tap below to open your signer app:
                  </p>
                  <a
                    :href="popupBlockedUri"
                    target="_blank"
                    rel="noopener noreferrer"
                    class="nostr-login-button w-full flex items-center justify-center gap-2 no-underline"
                  >
                    <img
                      src="@/assets/images/primal-icon.svg"
                      alt="Signer"
                      class="w-5 h-5 shrink-0"
                    />
                    Open Signer App
                  </a>
                </template>
              </template>
            </div>

            <!-- Sign in with Nostr Extension (NIP-07) -->
            <button
              @click="handleNostrLogin"
              :disabled="isLoading"
              class="nostr-login-button w-full flex items-center justify-center gap-2 mt-3"
            >
              <svg v-if="authLoading" class="w-5 h-5 shrink-0 animate-spin" fill="none" viewBox="0 0 24 24">
                <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
                <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
              </svg>
              <svg v-else class="w-5 h-5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" />
              </svg>
              {{ authLoading ? 'Signing in...' : 'Extension' }}
            </button>

            <!-- nsec login (hidden by default; tap to reveal field) -->
            <template v-if="!showNsecField">
              <button
                type="button"
                @click="showNsecField = true"
                :disabled="isLoading"
                class="nostr-login-button w-full flex items-center justify-center gap-2 mt-3"
              >
                <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
                </svg>
                Private Key
              </button>
            </template>
            <div v-else class="nsec-field-block mt-3">
              <input
                v-model="nsecInput"
                type="password"
                placeholder="nsec1..."
                class="auth-input w-full"
                autocomplete="off"
              />
              <div class="nsec-actions">
                <button
                  type="button"
                  @click="handleNsecSubmit"
                  :disabled="!nsecInput.trim() || isLoading"
                  class="nostr-login-button flex-1 flex items-center justify-center gap-2"
                  :class="{ 'opacity-40 cursor-not-allowed': !nsecInput.trim() || isLoading }"
                >
                  <svg v-if="authLoading" class="w-5 h-5 shrink-0 animate-spin" fill="none" viewBox="0 0 24 24">
                    <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
                    <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
                  </svg>
                  {{ authLoading ? 'Signing in...' : 'Sign in' }}
                </button>
                <button
                  type="button"
                  @click="cancelNsecField"
                  class="nsec-cancel-btn"
                >
                  Cancel
                </button>
              </div>
            </div>

            <!-- Amber Login (hidden for now — re-enable by changing v-if to amberPhase === 'idle') -->
            <template v-if="false">
            <button
              v-if="amberPhase === 'idle'"
              @click="handleAmberOpen"
              :disabled="isLoading"
              class="amber-login-button w-full flex items-center justify-center gap-2 mt-3"
            >
              <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none">
                <path d="M12 2L3 7v6c0 5.25 3.75 10.15 9 11.25C17.25 23.15 21 18.25 21 13V7l-9-5z" fill="#F7931A" opacity="0.2" stroke="#F7931A" stroke-width="1.5" stroke-linejoin="round"/>
                <path d="M12 8v4m0 0v4m0-4h4m-4 0H8" stroke="#F7931A" stroke-width="2" stroke-linecap="round"/>
              </svg>
              Sign in with Amber
            </button>
            <div v-else-if="amberPhase === 'waiting-pubkey'" class="mt-3 space-y-3">
              <div class="flex items-center justify-center gap-2 text-sm text-[#F7931A]">
                <svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
                  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                  <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
                </svg>
                <span>Waiting for Amber...</span>
              </div>
              <p class="text-xs text-white/40 text-center">Approve the request in Amber, then come back here</p>

              <!-- Paste fallback (shown after timeout) -->
              <div v-if="showPasteFallback" class="space-y-2 pt-2 border-t border-white/5">
                <p class="text-xs text-white/50 text-center">Clipboard didn't work? Paste your public key:</p>
                <div class="flex gap-2">
                  <input
                    v-model="amberPasteInput"
                    type="text"
                    placeholder="npub1... or hex pubkey"
                    class="auth-input flex-1 text-xs"
                  />
                  <button
                    @click="handleAmberPasteSubmit"
                    :disabled="!amberPasteInput.trim()"
                    class="amber-login-button px-4 text-xs"
                    :class="{ 'opacity-40 cursor-not-allowed': !amberPasteInput.trim() }"
                  >
                    Go
                  </button>
                </div>
              </div>

              <button
                @click="cancelAmber"
                class="w-full text-center text-sm text-white/40 hover:text-white/60 transition-colors"
              >
                Cancel
              </button>
            </div>

            <!-- Waiting for NIP-98 signature from Amber (auto-detects on return) -->
            <div v-else-if="amberPhase === 'waiting-signature'" class="mt-3 space-y-3">
              <div class="flex items-center justify-center gap-2 text-sm text-[#F7931A]">
                <svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
                  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                  <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
                </svg>
                <span>Approve sign-in in Amber...</span>
              </div>
              <p class="text-xs text-white/40 text-center">Approve the signing request, then come back here</p>

              <!-- Paste fallback (shown after timeout) -->
              <div v-if="showPasteFallback" class="space-y-2 pt-2 border-t border-white/5">
                <p class="text-xs text-white/50 text-center">Clipboard didn't work? Paste the signature:</p>
                <div class="flex gap-2">
                  <input
                    v-model="amberPasteInput"
                    type="text"
                    placeholder="Hex signature or signed event JSON"
                    class="auth-input flex-1 text-xs"
                  />
                  <button
                    @click="handleAmberSignPasteSubmit"
                    :disabled="!amberPasteInput.trim()"
                    class="amber-login-button px-4 text-xs"
                    :class="{ 'opacity-40 cursor-not-allowed': !amberPasteInput.trim() }"
                  >
                    Go
                  </button>
                </div>
              </div>

              <button
                @click="cancelAmber"
                class="w-full text-center text-sm text-white/40 hover:text-white/60 transition-colors"
              >
                Cancel
              </button>
            </div>

            <div v-else-if="amberPhase === 'completing'" class="mt-3">
              <div class="flex items-center justify-center gap-2 text-sm text-[#F7931A]">
                <svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
                  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                  <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
                </svg>
                <span>Completing sign-in...</span>
              </div>
            </div>
            </template>

            <!-- Toggle Mode -->
            <div class="mt-6 text-center text-sm text-white/60">
              {{ mode === 'register' ? 'Already have an account?' : "Don't have an account?" }}
              <button
                @click="toggleMode"
                class="ml-1 text-white hover:text-white/80 font-medium transition-colors"
              >
                {{ mode === 'register' ? 'Sign in' : 'Sign up' }}
              </button>
            </div>
            </template>
          </template>

          <!-- ═══ SOVEREIGN PHASE: NAH! ═══ -->
          <div v-else-if="sovereignPhase === 'nah'" class="sovereign-nah" key="nah">
            <span class="nah-text">STOP!</span>
          </div>

          <!-- ═══ SOVEREIGN PHASE: Own Your Privacy ═══ -->
          <div v-else-if="sovereignPhase === 'own-privacy'" class="sovereign-own-privacy" key="own-privacy">
            <div class="text-center space-y-6">
              <h2 class="own-privacy-heading">Own your privacy.</h2>
              <p class="text-white/50 text-base">No email. No password. No surveillance.</p>
              <button
                @click="handleGenerateSovereign"
                :disabled="isLoading"
                class="nostr-login-button sovereign-generate-btn w-full flex items-center justify-center gap-3"
              >
                <svg v-if="sovereignGenerating" class="w-5 h-5 shrink-0 animate-spin" fill="none" viewBox="0 0 24 24">
                  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
                  <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
                </svg>
                <svg v-else class="w-5 h-5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
                </svg>
                {{ sovereignGenerating ? 'Generating...' : 'Generate Sovereign Identity' }}
              </button>
              <button
                @click="sovereignDismissed = true; sovereignPhase = 'normal'"
                class="text-sm text-red-500/70 hover:text-red-400 transition-colors italic"
              >
                fuck you, I wanna be lame
              </button>
            </div>
          </div>

          <!-- ═══ SOVEREIGN PHASE: Generated — Download ═══ -->
          <div v-else-if="sovereignPhase === 'generated'" class="sovereign-generated" key="generated">
            <div class="text-center space-y-5">
              <div class="sovereign-check-circle">
                <svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
                </svg>
              </div>
              <h2 class="text-2xl font-bold text-white">You're sovereign.</h2>
              <p class="text-white/50 text-sm max-w-xs mx-auto leading-relaxed">
                Your new identity has been created and you're signed in. Download your keys now — if you lose them, <span class="text-red-400 font-medium">nobody can recover them</span>.
              </p>
              <button
                @click="downloadKeypair"
                class="download-identity-btn w-full flex items-center justify-center gap-3"
              >
                <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
                </svg>
                Download your new identity
              </button>
              <button
                @click="closeModal"
                class="text-sm text-white/40 hover:text-white/60 transition-colors"
              >
                I'll do it later (risky)
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </Transition>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import QRCode from 'qrcode'
import { useAuth } from '../composables/useAuth'
import { useAccounts } from '../composables/useAccounts'
import { useNostrConnect } from '../composables/useNostrConnect'
import { accountManager } from '../lib/accounts'
import { authService } from '../services/auth.service'

interface Props {
  isOpen: boolean
  defaultMode?: 'login' | 'register'
}

interface Emits {
  (e: 'close'): void
  (e: 'success'): void
}

const props = withDefaults(defineProps<Props>(), {
  defaultMode: 'register',
})

const emit = defineEmits<Emits>()

const { loginWithNostr, isLoading: authLoading } = useAuth()
const { loginWithExtension, loginWithPrivateKey } = useAccounts()
const {
  loginWithRemoteSigner,
  startRemoteSignerQrFlow,
  isLoading: nostrConnectLoading,
  error: nostrConnectError,
  popupBlockedUri,
} = useNostrConnect()

const isDesktop = !/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
const remoteSignerPhase = ref<'idle' | 'qr'>('idle')
const remoteSignerQrDataUrl = ref('')
const remoteSignerCopyText = ref('Copy URI')
const remoteSignerUri = ref('')
let remoteSignerCancel: (() => void) | null = null

const mode = ref<'login' | 'register' | 'forgot'>(props.defaultMode)
const errorMessage = ref<string | null>(null)
const isLoading = computed(
  () => authLoading.value || sovereignGenerating.value || nostrConnectLoading.value,
)

// nsec login (tap to reveal field)
const showNsecField = ref(false)
const nsecInput = ref('')

// Amber login state (hidden for now)
const amberPhase = ref<'idle' | 'waiting-pubkey' | 'waiting-signature' | 'completing'>('idle')
const amberPubkey = ref<string | null>(null)
const amberUnsignedEvent = ref<any>(null)
const amberPasteInput = ref('')
const showPasteFallback = ref(false)
let amberFallbackTimer: ReturnType<typeof setTimeout> | null = null
let amberVisibilityHandler: (() => void) | null = null

// ── Sovereign Identity Flow ──────────────────────────────────────
type SovereignPhase = 'normal' | 'nah' | 'own-privacy' | 'generated'
const sovereignPhase = ref<SovereignPhase>('normal')
const sovereignGenerating = ref(false)
const sovereignDismissed = ref(false)

// Store the generated keypair so it can be downloaded
const generatedKeys = ref<{ nsec: string; npub: string; hexSecret: string; hexPub: string } | null>(null)

// Reset sovereign phase when modal reopens
watch(() => props.isOpen, (open) => {
  if (open) {
    sovereignPhase.value = 'normal'
    sovereignDismissed.value = false
    generatedKeys.value = null
    errorMessage.value = null
    showNsecField.value = false
    nsecInput.value = ''
    remoteSignerPhase.value = 'idle'
    remoteSignerQrDataUrl.value = ''
    remoteSignerUri.value = ''
    remoteSignerCancel?.()
    remoteSignerCancel = null
    cancelAmber()
  }
})

// Surface Nostr Connect errors in the modal
watch(nostrConnectError, (err) => {
  if (err) errorMessage.value = err
})

function closeModal() {
  remoteSignerCancel?.()
  remoteSignerCancel = null
  emit('close')
  errorMessage.value = null
  cancelAmber()
  sovereignPhase.value = 'normal'
  sovereignDismissed.value = false
  generatedKeys.value = null
}

function toggleMode() {
  mode.value = mode.value === 'login' ? 'register' : 'login'
  errorMessage.value = null
}

/**
 * Intercept clicks on the legacy auth form.
 * Triggers the "STOP!" → sovereign identity animation.
 * Skipped if the user already dismissed the sovereign flow.
 */
function triggerSovereignFlow(e: Event) {
  if (sovereignDismissed.value) return
  e.preventDefault()
  e.stopPropagation()
  sovereignPhase.value = 'nah'

  // After "STOP!" animation plays, transition to the privacy message
  setTimeout(() => {
    sovereignPhase.value = 'own-privacy'
  }, 1400)
}

/**
 * Generate a brand new Nostr keypair, log the user in,
 * and transition to the download phase.
 */
async function handleGenerateSovereign() {
  errorMessage.value = null
  sovereignGenerating.value = true

  try {
    // Dynamic import to keep bundle size lean
    const { generateSecretKey, getPublicKey } = await import('nostr-tools/pure')
    const nip19 = await import('nostr-tools/nip19')

    const secretKey = generateSecretKey()
    const pubkey = getPublicKey(secretKey)

    const nsec = nip19.nsecEncode(secretKey)
    const npub = nip19.npubEncode(pubkey)
    const hexSecret = Array.from(secretKey).map(b => b.toString(16).padStart(2, '0')).join('')

    generatedKeys.value = { nsec, npub, hexSecret, hexPub: pubkey }

    // Register in account manager using applesauce's PrivateKeyAccount
    const { PrivateKeyAccount } = await import('applesauce-accounts/accounts/private-key-account')
    const account = PrivateKeyAccount.fromKey(secretKey)
    accountManager.addAccount(account)
    accountManager.setActive(account)

    // Create backend auth session
    await loginWithNostr(pubkey, 'generated', {})

    sovereignPhase.value = 'generated'
    emit('success')
  } catch (error: any) {
    console.error('Sovereign identity generation failed:', error)
    errorMessage.value = error.message || 'Failed to generate identity. Please try again.'
  } finally {
    sovereignGenerating.value = false
  }
}

/**
 * Download the generated keypair as a text file.
 */
function downloadKeypair() {
  if (!generatedKeys.value) return

  const { nsec, npub, hexSecret, hexPub } = generatedKeys.value
  const content = [
    '═══════════════════════════════════════════════════════',
    '  YOUR SOVEREIGN NOSTR IDENTITY — KEEP THIS SAFE!',
    '═══════════════════════════════════════════════════════',
    '',
    'Generated: ' + new Date().toISOString(),
    '',
    '── Public Key (share freely) ──────────────────────────',
    'npub:  ' + npub,
    'hex:   ' + hexPub,
    '',
    '── Secret Key (NEVER share this!) ────────────────────',
    'nsec:  ' + nsec,
    'hex:   ' + hexSecret,
    '',
    '═══════════════════════════════════════════════════════',
    '  WARNING: If you lose this file, your identity is',
    '  gone forever. Nobody can recover it for you.',
    '  Store it somewhere safe (password manager, USB, etc.)',
    '═══════════════════════════════════════════════════════',
    '',
  ].join('\n')

  const blob = new Blob([content], { type: 'text/plain' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `nostr-identity-${npub.slice(0, 12)}.txt`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
}

async function handleNostrLogin() {
  errorMessage.value = null

  try {
    // Check for Nostr extension (NIP-07)
    if (!window.nostr) {
      errorMessage.value = 'Nostr extension not found. Please install a Nostr browser extension like Alby or nos2x.'
      return
    }

    // First, register the extension account in accountManager.
    // This sets up the signer that createNip98AuthHeader needs.
    await loginWithExtension()

    const pubkey = accountManager.active?.pubkey
    if (!pubkey) {
      errorMessage.value = 'Could not get public key from extension.'
      return
    }

    // Create backend session (NIP-98 auth is handled internally
    // by authService using the active accountManager signer)
    await loginWithNostr(pubkey, 'extension', {})

    emit('success')
    closeModal()
  } catch (error: any) {
    console.error('Nostr login failed:', error)
    errorMessage.value = error.message || 'Nostr authentication failed. Please try again.'
  }
}

/**
 * Desktop: Open Remote Signer QR phase.
 */
async function handleRemoteSignerClick() {
  errorMessage.value = null
  remoteSignerPhase.value = 'qr'
  remoteSignerQrDataUrl.value = ''
  remoteSignerUri.value = ''
  remoteSignerCopyText.value = 'Copy URI'

  try {
    const { uri, complete, cancel } = startRemoteSignerQrFlow()
    remoteSignerCancel = cancel
    remoteSignerUri.value = uri

    const dataUrl = await QRCode.toDataURL(uri, {
      width: 224,
      margin: 2,
      color: { dark: '#000000', light: '#FFFFFF' },
      errorCorrectionLevel: 'M',
    })
    remoteSignerQrDataUrl.value = dataUrl

    await complete
    emit('success')
    closeModal()
  } catch (error: any) {
    if (remoteSignerPhase.value === 'qr') {
      errorMessage.value = error?.message || 'Remote signer login failed. Please try again.'
    }
  } finally {
    remoteSignerCancel = null
  }
}

/**
 * Back from Remote Signer QR phase.
 */
function handleRemoteSignerBack() {
  remoteSignerCancel?.()
  remoteSignerCancel = null
  remoteSignerPhase.value = 'idle'
  remoteSignerQrDataUrl.value = ''
  remoteSignerUri.value = ''
  errorMessage.value = null
}

async function copyRemoteSignerUri() {
  if (!remoteSignerUri.value) return
  try {
    await navigator.clipboard.writeText(remoteSignerUri.value)
    remoteSignerCopyText.value = 'Copied!'
    setTimeout(() => { remoteSignerCopyText.value = 'Copy URI' }, 2000)
  } catch {
    remoteSignerCopyText.value = 'Copy failed'
  }
}

/**
 * Login with Nostr via remote signer (Primal, etc.) using nostrconnect:// URI.
 * Mobile: Opens the signer via link, waits for connection, then creates backend session.
 */
async function handleNostrConnectLogin() {
  errorMessage.value = null

  try {
    await loginWithRemoteSigner()
    emit('success')
    closeModal()
  } catch (error: any) {
    console.error('Nostr Connect login failed:', error)
    errorMessage.value = error?.message || 'Remote signer login failed. Please try again.'
  }
}

function cancelNsecField() {
  showNsecField.value = false
  nsecInput.value = ''
  errorMessage.value = null
}

/**
 * Sign in with pasted nsec. Adds account, sets active, then creates backend session.
 */
async function handleNsecSubmit() {
  const nsec = nsecInput.value.trim()
  if (!nsec) return
  errorMessage.value = null
  try {
    await loginWithPrivateKey(nsec)
    const account = accountManager.active
    if (!account) throw new Error('Account not set')
    await loginWithNostr(account.pubkey, 'nsec', {}, undefined)
    nsecInput.value = ''
    showNsecField.value = false
    emit('success')
    closeModal()
  } catch (err: any) {
    errorMessage.value = err.message || 'Invalid nsec or sign-in failed.'
  }
}

/**
 * Clean up Amber flow state, timers, and event listeners.
 */
function cancelAmber() {
  amberPhase.value = 'idle'
  amberPubkey.value = null
  amberUnsignedEvent.value = null
  amberPasteInput.value = ''
  showPasteFallback.value = false
  if (amberFallbackTimer) {
    clearTimeout(amberFallbackTimer)
    amberFallbackTimer = null
  }
  if (amberVisibilityHandler) {
    document.removeEventListener('visibilitychange', amberVisibilityHandler)
    amberVisibilityHandler = null
  }
}

/**
 * Start listening for the user to return from Amber.
 * On visibilitychange → visible, waits 500ms then tries to read
 * clipboard. If clipboard read fails or is empty, shows paste fallback.
 *
 * @param onSuccess Called with clipboard text when auto-read succeeds.
 */
function listenForAmberReturn(onSuccess: (text: string) => void) {
  // Show paste fallback after 8 seconds regardless
  amberFallbackTimer = setTimeout(() => {
    showPasteFallback.value = true
  }, 8000)

  amberVisibilityHandler = () => {
    if (document.visibilityState !== 'visible') return

    // User returned to browser — try clipboard after a short delay
    // (same 500ms + 200ms pattern as AmberClipboardSigner)
    setTimeout(async () => {
      try {
        if (!navigator.clipboard?.readText) {
          showPasteFallback.value = true
          return
        }
        const text = (await navigator.clipboard.readText()).trim()
        if (!text) {
          showPasteFallback.value = true
          return
        }
        // Clipboard read succeeded — clean up listener and proceed
        if (amberVisibilityHandler) {
          document.removeEventListener('visibilitychange', amberVisibilityHandler)
          amberVisibilityHandler = null
        }
        if (amberFallbackTimer) {
          clearTimeout(amberFallbackTimer)
          amberFallbackTimer = null
        }
        onSuccess(text)
      } catch {
        // Clipboard permission denied or other error — show paste input
        showPasteFallback.value = true
      }
    }, 600)
  }

  document.addEventListener('visibilitychange', amberVisibilityHandler)
}

/**
 * Amber Login — Step 1: Open Amber to get the public key.
 * Sets up auto-detection via visibilitychange for when the user returns.
 */
function handleAmberOpen() {
  errorMessage.value = null
  showPasteFallback.value = false
  amberPasteInput.value = ''

  const isAndroid = navigator.userAgent.includes('Android')
  if (!isAndroid) {
    errorMessage.value = 'Amber is only available on Android devices. Please use a Nostr browser extension instead.'
    return
  }

  // Open Amber via intent to get pubkey
  const intent = 'intent:#Intent;scheme=nostrsigner;S.compressionType=none;S.returnType=signature;S.type=get_public_key;end'
  window.open(intent, '_blank')

  amberPhase.value = 'waiting-pubkey'

  // Auto-detect: when user returns, try to read pubkey from clipboard
  listenForAmberReturn((clipboardText) => {
    processPubkey(clipboardText)
  })
}

/**
 * Decode a pubkey from text. Handles hex, npub, nprofile, and JSON (e.g. pasted NIP-98 event).
 * Normalizes pasted content: trims, strips newlines, accepts hex with extra characters.
 */
async function decodePubkeyText(text: string): Promise<string> {
  const raw = text.trim().replace(/\s+/g, '')
  if (!raw) throw new Error('Not a valid public key. Expected hex or npub format.')

  // JSON: e.g. pasted NIP-98 request or signed event from Amber (use trim only so JSON stays valid)
  if (raw.startsWith('{')) {
    try {
      const parsed = JSON.parse(text.trim())
      if (parsed.pubkey && /^[0-9a-f]{64}$/i.test(String(parsed.pubkey))) {
        return String(parsed.pubkey)
      }
    } catch {
      // Not valid JSON, fall through
    }
  }

  // Exact 64-char hex
  if (/^[0-9a-f]{64}$/i.test(raw)) return raw

  // Hex with extra chars: take first 64 hex characters
  const hexOnly = raw.replace(/[^0-9a-fA-F]/g, '')
  if (hexOnly.length >= 64) {
    return hexOnly.slice(0, 64)
  }

  // npub / nprofile
  const trimmed = text.trim()
  if (trimmed.startsWith('npub') || trimmed.startsWith('nprofile')) {
    const { decodeProfilePointer } = await import('applesauce-core/helpers')
    const decoded = decodeProfilePointer(trimmed)
    if (!decoded?.pubkey) throw new Error('Could not decode npub')
    return decoded.pubkey
  }

  throw new Error('Not a valid public key. Expected hex or npub format.')
}

/**
 * Process a pubkey (from auto-read or paste), then open Amber to sign NIP-98.
 * If the user pasted a full signed NIP-98 event (e.g. from Amber), complete login directly.
 */
async function processPubkey(text: string) {
  errorMessage.value = null
  try {
    // If they pasted the signed event JSON from Amber, complete login without opening Amber again
    const trimmed = text.trim()
    if (trimmed.startsWith('{')) {
      try {
        const parsed = JSON.parse(trimmed)
        if (parsed.sig && parsed.pubkey && /^[0-9a-f]{64}$/i.test(String(parsed.pubkey))) {
          await processSignature(trimmed)
          return
        }
      } catch {
        // Not a signed event, continue to pubkey extraction
      }
    }

    const pubkey = await decodePubkeyText(text)
    amberPubkey.value = pubkey
    showPasteFallback.value = false
    amberPasteInput.value = ''

    // Build the unsigned NIP-98 event (name tag so Amber shows "IndeeHub" not "null")
    const sessionUrl = authService.getNostrSessionUrl()
    const unsignedEvent = {
      kind: 27235,
      created_at: Math.floor(Date.now() / 1000),
      tags: [
        ['u', sessionUrl],
        ['method', 'POST'],
        ['name', 'IndeeHub'],
      ],
      content: '',
      pubkey,
    }
    amberUnsignedEvent.value = unsignedEvent

    // Open Amber to sign this event
    const eventJson = JSON.stringify(unsignedEvent)
    const intent = `intent:${encodeURIComponent(eventJson)}#Intent;scheme=nostrsigner;S.compressionType=none;S.returnType=signature;S.type=sign_event;end`
    window.open(intent, '_blank')

    amberPhase.value = 'waiting-signature'

    // Auto-detect: when user returns, try to read signature from clipboard
    listenForAmberReturn((clipboardText) => {
      processSignature(clipboardText)
    })
  } catch (err: any) {
    errorMessage.value = err.message || 'Invalid public key. Please try again.'
    showPasteFallback.value = true
  }
}

/**
 * Manual paste submit for pubkey.
 */
function handleAmberPasteSubmit() {
  const text = amberPasteInput.value.trim()
  if (!text) return
  processPubkey(text)
}

/**
 * Process a signature (from auto-read or paste) and complete login.
 */
async function processSignature(text: string) {
  errorMessage.value = null

  const pubkey = amberPubkey.value
  if (!pubkey) { errorMessage.value = 'Lost pubkey. Please start over.'; cancelAmber(); return }
  const storedEvent = amberUnsignedEvent.value
  if (!storedEvent) { errorMessage.value = 'Lost signing request. Please start over.'; cancelAmber(); return }

  amberPhase.value = 'completing'

  try {
    let authHeader: string

    // Full signed event JSON
    if (text.startsWith('{')) {
      const signedEvent = JSON.parse(text)
      if (!signedEvent.sig) throw new Error('Signed event missing signature')
      authHeader = `Nostr ${btoa(JSON.stringify(signedEvent))}`
    }
    // Hex signature — combine with stored unsigned event
    else if (/^[0-9a-f]+$/i.test(text)) {
      const event = { ...storedEvent, sig: text }
      const { getEventHash } = await import('nostr-tools/pure')
      event.id = getEventHash(event as any)
      authHeader = `Nostr ${btoa(JSON.stringify(event))}`
    }
    else {
      throw new Error('Unrecognised signature format from Amber.')
    }

    // Authenticate with the pre-signed NIP-98 header
    await loginWithNostr(pubkey, 'amber-nip55', {}, authHeader)

    // Register the Amber account in accountManager
    try {
      const { AmberClipboardSigner, AmberClipboardAccount } = await import('../lib/accounts')
      const signer = new AmberClipboardSigner()
      signer.pubkey = pubkey
      const account = new AmberClipboardAccount(pubkey, signer)
      accountManager.addAccount(account)
      accountManager.setActive(account)
    } catch (accountErr) {
      console.warn('[Amber] Account registration after login:', accountErr)
    }

    cancelAmber()
    emit('success')
    closeModal()
  } catch (err: any) {
    console.error('Amber sign-in failed:', err)
    errorMessage.value = err.message || 'Failed to complete Amber sign-in. Please try again.'
    amberPhase.value = 'waiting-signature'
    showPasteFallback.value = true
  }
}

/**
 * Manual paste submit for signature.
 */
function handleAmberSignPasteSubmit() {
  const text = amberPasteInput.value.trim()
  if (!text) return
  processSignature(text)
}

// Declare window.nostr for TypeScript
declare global {
  interface Window {
    nostr?: {
      getPublicKey: () => Promise<string>
      signEvent: (event: any) => Promise<any>
    }
  }
}
</script>

<style scoped>
.auth-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 9998;
  background: rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.auth-modal-container {
  width: 100%;
  max-width: 480px;
  max-height: 90vh;
  overflow-y: auto;
}

.auth-modal-content {
  position: relative;
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(40px);
  -webkit-backdrop-filter: blur(40px);
  border-radius: 24px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: 
    0 20px 60px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.1);
  padding: 32px;
}

.auth-input {
  width: 100%;
  padding: 12px 16px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  color: white;
  font-size: 14px;
  transition: all 0.3s ease;
}

.auth-input:focus {
  outline: none;
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.2);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.05);
}

.auth-input::placeholder {
  color: rgba(255, 255, 255, 0.3);
}

/* nsec login field block */
.nsec-field-block {
  padding: 0.5rem 0;
}
.nsec-hint {
  font-size: 0.8125rem;
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: 0.5rem;
  line-height: 1.4;
}
.nsec-field-block .auth-input {
  margin-bottom: 0.5rem;
}
.nsec-actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-top: 0.5rem;
}
.nsec-cancel-btn {
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.6);
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.nsec-cancel-btn:hover {
  color: rgba(255, 255, 255, 0.9);
  border-color: rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.05);
}

/* Modal Transitions */
.modal-fade-enter-active,
.modal-fade-leave-active {
  transition: opacity 0.3s ease;
}

.modal-fade-enter-from,
.modal-fade-leave-to {
  opacity: 0;
}

.modal-fade-enter-active .auth-modal-content {
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.modal-fade-enter-from .auth-modal-content {
  transform: scale(0.95);
  opacity: 0;
}

/* Nostr Extension Login Button — dark glass style */
.nostr-login-button {
  position: relative;
  height: 48px;
  padding: 0 24px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
  border-radius: 16px;
  background: rgba(0, 0, 0, 0.35);
  color: rgba(255, 255, 255, 0.92);
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  cursor: pointer;
  transition: all 0.3s ease;
  letter-spacing: 0.02em;
}

.nostr-login-button:hover:not(:disabled) {
  transform: translateY(-2px);
  background: rgba(0, 0, 0, 0.5);
  border-color: rgba(255, 255, 255, 0.15);
  box-shadow:
    0 12px 32px rgba(0, 0, 0, 0.6),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.nostr-login-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Amber Login Button */
.amber-login-button {
  height: 48px;
  padding: 0 24px;
  border-radius: 12px;
  font-weight: 600;
  font-size: 14px;
  color: #F7931A;
  background: rgba(247, 147, 26, 0.08);
  border: 1px solid rgba(247, 147, 26, 0.25);
  cursor: pointer;
  transition: all 0.3s ease;
}

.amber-login-button:hover {
  background: rgba(247, 147, 26, 0.15);
  border-color: rgba(247, 147, 26, 0.4);
  box-shadow: 0 0 20px rgba(247, 147, 26, 0.1);
}

.amber-login-button--active {
  background: rgba(247, 147, 26, 0.15);
  border-color: rgba(247, 147, 26, 0.5);
  box-shadow: 0 0 24px rgba(247, 147, 26, 0.15);
}

.amber-login-button--active:hover {
  background: rgba(247, 147, 26, 0.22);
  box-shadow: 0 0 30px rgba(247, 147, 26, 0.2);
}

.amber-login-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ── Sovereign Identity Flow ──────────────────────────────────── */

/* The form area that intercepts clicks */
.sovereign-trap {
  cursor: pointer;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.sovereign-trap:hover {
  opacity: 0.85;
}

/* ── Close Button — matches film detail modal ── */
.auth-close-btn {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 20;
  padding: 8px;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-radius: 9999px;
  color: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(255, 255, 255, 0.08);
  cursor: pointer;
  transition: all 0.2s ease;
}

.auth-close-btn:hover {
  color: white;
  background: rgba(0, 0, 0, 0.8);
  border-color: rgba(255, 255, 255, 0.15);
}

/* ── NAH! Phase — left-to-right reveal ── */
.sovereign-nah {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 280px;
  overflow: hidden;
}

.nah-text {
  font-size: clamp(4rem, 12vw, 7rem);
  font-weight: 900;
  letter-spacing: -0.04em;
  background: linear-gradient(135deg, #ffffff 0%, #ff4444 50%, #ff0000 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: none;
  filter: drop-shadow(0 0 40px rgba(255, 0, 0, 0.3));

  /* Left-to-right fade-slide with a slight scale punch */
  animation:
    nahSlideIn 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards,
    nahGlow 0.9s ease-in-out 0.3s;
}

@keyframes nahSlideIn {
  0% {
    opacity: 0;
    transform: translateX(-60px) scale(0.85);
    filter: drop-shadow(0 0 0 rgba(255, 0, 0, 0));
  }
  70% {
    opacity: 1;
    transform: translateX(8px) scale(1.05);
  }
  100% {
    opacity: 1;
    transform: translateX(0) scale(1);
    filter: drop-shadow(0 0 40px rgba(255, 0, 0, 0.3));
  }
}

@keyframes nahGlow {
  0%, 100% { filter: drop-shadow(0 0 40px rgba(255, 0, 0, 0.3)); }
  50% { filter: drop-shadow(0 0 80px rgba(255, 0, 0, 0.6)); }
}

/* ── Own Your Privacy Phase — left-to-right fade ── */
.sovereign-own-privacy {
  min-height: 280px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.sovereign-own-privacy > div {
  animation: privacySlideIn 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.own-privacy-heading {
  font-size: clamp(1.75rem, 5vw, 2.5rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  background: linear-gradient(to right, #ffffff, rgba(255, 255, 255, 0.6));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@keyframes privacySlideIn {
  0% {
    opacity: 0;
    transform: translateX(-40px);
  }
  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

.sovereign-generate-btn {
  padding: 14px 28px !important;
  font-size: 15px !important;
}

/* ── Generated / Download Phase ── */
.sovereign-generated {
  min-height: 280px;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: generatedFadeIn 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@keyframes generatedFadeIn {
  0% {
    transform: scale(0.9);
    opacity: 0;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.sovereign-check-circle {
  width: 64px;
  height: 64px;
  margin: 0 auto;
  border-radius: 50%;
  background: rgba(34, 197, 94, 0.15);
  border: 2px solid rgba(34, 197, 94, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #22c55e;
  animation: checkPop 0.5s cubic-bezier(0.16, 1, 0.3, 1) 0.1s both;
}

@keyframes checkPop {
  0% {
    transform: scale(0);
    opacity: 0;
  }
  60% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* Red glassmorphism download button */
.download-identity-btn {
  position: relative;
  padding: 14px 28px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  border-radius: 16px;
  background: rgba(220, 38, 38, 0.2);
  color: #fca5a5;
  box-shadow:
    0 8px 32px rgba(220, 38, 38, 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid rgba(220, 38, 38, 0.35);
  cursor: pointer;
  transition: all 0.3s ease;
  letter-spacing: 0.02em;
}

.download-identity-btn:hover {
  transform: translateY(-2px);
  background: rgba(220, 38, 38, 0.3);
  border-color: rgba(220, 38, 38, 0.5);
  color: #fecaca;
  box-shadow:
    0 12px 40px rgba(220, 38, 38, 0.35),
    0 0 60px rgba(220, 38, 38, 0.1),
    inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
</style>
