<script setup lang="ts">
import { ref, nextTick, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { eventBus } from '@/common/eventBus'
import {
  authenticateParent,
  isParentAuthenticated,
  isParentPersistent,
  logoutParent,
  logoutUser,
  consumePendingReturnUrl,
  hasPendingReturnUrl,
  clearPendingReturnUrl,
} from '../../stores/auth'
import { getCachedImageBlob } from '@/common/imageCache'
import '@/assets/styles.css'
import ModalDialog from './ModalDialog.vue'
import {
  subscribeToPushWithResult,
  unsubscribeFromPush,
  isPushOptedOut,
  ensurePushSubscriptionSynced,
} from '@/services/pushSubscription'
import {
  hydrateFromProfile as hydrateTutorial,
  maybeShow as tutorialMaybeShow,
} from '@/tutorial/controller'

const router = useRouter()
const show = ref(false)
const pin = ref('')
const error = ref('')
const stayInParentMode = ref(false)
const pinInput = ref<HTMLInputElement | null>(null)
const dropdownOpen = ref(false)
const dropdownRef = ref<HTMLElement | null>(null)
const avatarButtonRef = ref<HTMLButtonElement | null>(null)
const focusedMenuIndex = ref(0)

// User profile data
const userImageId = ref<string | null>(null)
const userFirstName = ref<string>('')
const userEmail = ref<string>('')
const profileLoading = ref(true)
const avatarImageUrl = ref<string | null>(null)
const dropdownAvatarImageUrl = ref<string | null>(null)

// Compute avatar initial
const avatarInitial = ref<string>('?')

// Fetch user profile
async function fetchUserProfile() {
  try {
    const res = await fetch('/api/user/profile', { credentials: 'include' })
    if (!res.ok) {
      console.error('Failed to fetch user profile')
      profileLoading.value = false
      return
    }
    const data = await res.json()
    userImageId.value = data.image_id || null
    userFirstName.value = data.first_name || ''
    userEmail.value = data.email || ''
    hydrateTutorial({
      tutorial_enabled: data.tutorial_enabled,
      tutorial_progress: data.tutorial_progress,
    })
    void maybeShowSetupPinTutorial()

    // Update avatar initial
    avatarInitial.value = userFirstName.value ? userFirstName.value.charAt(0).toUpperCase() : '?'

    profileLoading.value = false

    // Load cached image if available
    if (userImageId.value) {
      await loadAvatarImages(userImageId.value)
    }

    // Silent startup self-heal: if user has push enabled, ensure browser + backend
    // subscription state are synchronized (no permission prompt).
    if (
      isParentAuthenticated.value &&
      data.push_notifications_enabled !== false &&
      !isPushOptedOut()
    ) {
      void ensurePushSubscriptionSynced()
    }
  } catch (e) {
    console.error('Error fetching user profile:', e)
    profileLoading.value = false
  }
}

async function maybeShowSetupPinTutorial() {
  try {
    const res = await fetch('/api/user/has-pin', { credentials: 'include' })
    if (!res.ok) return
    const data = await res.json()
    if (!data.has_pin) {
      tutorialMaybeShow('setup-parent-pin', () => avatarButtonRef.value)
    }
  } catch {
    // Silent: tutorial just won't fire.
  }
}

async function loadAvatarImages(imageId: string) {
  try {
    const blob = await getCachedImageBlob(imageId)
    // Clean up previous URLs
    if (avatarImageUrl.value) URL.revokeObjectURL(avatarImageUrl.value)
    if (dropdownAvatarImageUrl.value) URL.revokeObjectURL(dropdownAvatarImageUrl.value)
    avatarImageUrl.value = URL.createObjectURL(blob)
    dropdownAvatarImageUrl.value = URL.createObjectURL(blob)
  } catch (e) {
    avatarImageUrl.value = null
    dropdownAvatarImageUrl.value = null
  }
}

const open = async () => {
  // Check if user has a pin
  try {
    const res = await fetch('/api/user/has-pin', { credentials: 'include' })
    const data = await res.json()
    if (!res.ok) throw new Error(data.error || 'Error checking PIN')
    if (!data.has_pin) {
      console.log('No PIN set, redirecting to setup')
      // Route to PIN setup view
      router.push('/parent/pin-setup')
      return
    }
  } catch (e) {
    error.value = 'Network error'
    return
  }
  pin.value = ''
  error.value = ''
  show.value = true
  await nextTick()
  pinInput.value?.focus()
}

const close = () => {
  show.value = false
  error.value = ''
  stayInParentMode.value = false
  clearPendingReturnUrl()
}

const submit = async () => {
  const isDigits = /^\d{4,6}$/.test(pin.value)
  if (!isDigits) {
    error.value = 'Enter 4–6 digits'
    return
  }

  try {
    const res = await fetch('/api/user/check-pin', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ pin: pin.value }),
      credentials: 'include',
    })
    const data = await res.json()
    if (!res.ok) {
      error.value = data.error || 'Error validating PIN'
      return
    }
    if (!data.valid) {
      error.value = 'Incorrect PIN'
      pin.value = ''
      await nextTick()
      pinInput.value?.focus()
      return
    }
    // Authenticate parent and navigate
    authenticateParent(stayInParentMode.value)
    if (!isPushOptedOut()) {
      subscribeToPushWithResult() // fire-and-forget — browser gesture is satisfied by the PIN button click
    }
    const returnUrl = consumePendingReturnUrl()
    close()
    router.push(returnUrl || '/parent')
  } catch (e) {
    error.value = 'Network error'
  }
}

function handlePinInput(event: Event) {
  const target = event.target as HTMLInputElement
  pin.value = target.value.replace(/\D/g, '').slice(0, 6)
}

const handleLogout = () => {
  unsubscribeFromPush()
  logoutParent()
  router.push('/child')
}

function toggleDropdown() {
  dropdownOpen.value = !dropdownOpen.value
  if (dropdownOpen.value) {
    focusedMenuIndex.value = 0
  }
}

function closeDropdown() {
  dropdownOpen.value = false
  focusedMenuIndex.value = 0
  avatarButtonRef.value?.focus()
}

function handleKeyDown(event: KeyboardEvent) {
  if (!dropdownOpen.value) {
    // Handle avatar button keyboard
    if (event.key === 'Enter' || event.key === ' ') {
      event.preventDefault()
      if (isParentAuthenticated.value) {
        toggleDropdown()
      } else {
        open()
      }
    }
    return
  }

  // Handle dropdown keyboard navigation
  const menuItems = 3 // Profile, Child Mode, Sign Out

  switch (event.key) {
    case 'ArrowDown':
      event.preventDefault()
      focusedMenuIndex.value = (focusedMenuIndex.value + 1) % menuItems
      break
    case 'ArrowUp':
      event.preventDefault()
      focusedMenuIndex.value = (focusedMenuIndex.value - 1 + menuItems) % menuItems
      break
    case 'Enter':
    case ' ':
      event.preventDefault()
      executeMenuItem(focusedMenuIndex.value)
      break
    case 'Escape':
      event.preventDefault()
      closeDropdown()
      break
    case 'Tab':
      closeDropdown()
      break
  }
}

function executeMenuItem(index: number) {
  switch (index) {
    case 0:
      goToProfile()
      break
    case 1:
      handleLogout()
      closeDropdown()
      break
    case 2:
      signOut()
      break
  }
}

async function signOut() {
  try {
    await fetch('/api/auth/logout', { method: 'POST' })
    logoutParent()
    logoutUser()
    router.push('/')
  } catch {
    // Optionally show error
  }
  closeDropdown()
}

function goToProfile() {
  router.push('/parent/profile')
  closeDropdown()
}

function handleClickOutside(event: MouseEvent) {
  if (
    dropdownOpen.value &&
    dropdownRef.value &&
    !dropdownRef.value.contains(event.target as Node)
  ) {
    closeDropdown()
  }
}

onMounted(() => {
  eventBus.on('open-login', open)
  eventBus.on('profile_updated', fetchUserProfile)
  document.addEventListener('mousedown', handleClickOutside)
  fetchUserProfile()
  if (!isParentAuthenticated.value && hasPendingReturnUrl()) {
    open()
  }
})

onUnmounted(() => {
  eventBus.off('open-login', open)
  eventBus.off('profile_updated', fetchUserProfile)
  document.removeEventListener('mousedown', handleClickOutside)

  // Revoke object URL to free memory
  if (avatarImageUrl.value) URL.revokeObjectURL(avatarImageUrl.value)
  if (dropdownAvatarImageUrl.value) URL.revokeObjectURL(dropdownAvatarImageUrl.value)
})
</script>

<template>
  <div style="position: relative">
    <button
      ref="avatarButtonRef"
      @click="isParentAuthenticated ? toggleDropdown() : open()"
      @keydown="handleKeyDown"
      :aria-label="isParentAuthenticated ? 'Parent menu' : 'Parent login'"
      aria-haspopup="menu"
      :aria-expanded="isParentAuthenticated && dropdownOpen ? 'true' : 'false'"
      class="avatar-btn"
    >
      <img
        v-if="avatarImageUrl && !profileLoading"
        :src="avatarImageUrl"
        :alt="userFirstName || 'User avatar'"
        class="avatar-image"
      />
      <span v-else class="avatar-text">{{ profileLoading ? '...' : avatarInitial }}</span>
    </button>
    <span
      v-if="isParentAuthenticated && isParentPersistent"
      class="persistent-badge"
      aria-label="Persistent parent mode active"
      >🔒</span
    >

    <Transition name="slide-fade">
      <div
        v-if="isParentAuthenticated && dropdownOpen"
        ref="dropdownRef"
        role="menu"
        class="dropdown-menu"
      >
        <div class="dropdown-header">
          <img
            v-if="avatarImageUrl"
            :src="avatarImageUrl"
            :alt="userFirstName || 'User avatar'"
            class="dropdown-avatar"
          />
          <span v-else class="dropdown-avatar-initial">{{ avatarInitial }}</span>
          <div class="dropdown-user-info">
            <div class="dropdown-user-name">{{ userFirstName || 'User' }}</div>
            <div v-if="userEmail" class="dropdown-user-email">{{ userEmail }}</div>
          </div>
        </div>

        <button
          role="menuitem"
          :aria-selected="focusedMenuIndex === 0"
          :class="['menu-item', { focused: focusedMenuIndex === 0 }]"
          @mouseenter="focusedMenuIndex = 0"
          @click="goToProfile"
        >
          <span class="menu-icon-stub">
            <img
              src="/profile.png"
              alt="Profile"
              style="width: 20px; height: 20px; object-fit: contain; vertical-align: middle"
            />
          </span>
          <span>Profile</span>
        </button>
        <button
          role="menuitem"
          :aria-selected="focusedMenuIndex === 1"
          :class="['menu-item', { focused: focusedMenuIndex === 1 }]"
          @mouseenter="focusedMenuIndex = 1"
          @click="
            () => {
              handleLogout()
              closeDropdown()
            }
          "
        >
          <span class="menu-icon-stub">
            <img
              src="/child-mode.png"
              alt="Child Mode"
              style="width: 20px; height: 20px; object-fit: contain; vertical-align: middle"
            />
          </span>
          <span>Child Mode</span>
        </button>
        <button
          role="menuitem"
          :aria-selected="focusedMenuIndex === 2"
          :class="['menu-item', 'danger', { focused: focusedMenuIndex === 2 }]"
          @mouseenter="focusedMenuIndex = 2"
          @click="signOut"
        >
          <span class="menu-icon-stub">
            <img
              src="/sign-out.png"
              alt="Sign out"
              style="width: 20px; height: 20px; object-fit: contain; vertical-align: middle"
            />
          </span>
          <span>Sign out</span>
        </button>
      </div>
    </Transition>

    <ModalDialog v-if="show" title="Enter parent PIN" @click.self="close" @close="close">
      <form @submit.prevent="submit">
        <input
          ref="pinInput"
          v-model="pin"
          @input="handlePinInput"
          inputmode="numeric"
          pattern="\d*"
          maxlength="6"
          placeholder="4–6 digits"
          class="pin-input"
        />
        <label class="stay-label">
          <input type="checkbox" v-model="stayInParentMode" class="stay-checkbox" />
          Stay in parent mode on this device
        </label>
        <div class="actions modal-actions">
          <button type="button" class="btn btn-secondary" @click="close">Cancel</button>
          <button type="submit" class="btn btn-primary" :disabled="pin.length < 4">OK</button>
        </div>
      </form>
      <div v-if="error" class="error modal-message">{{ error }}</div>
    </ModalDialog>
  </div>
</template>

<style scoped>
.error {
  color: var(--error);
}

.avatar-btn {
  width: 44px;
  min-width: 44px;
  max-width: 44px;
  height: 44px;
  min-height: 44px;
  max-height: 44px;
  margin: 0;
  background: var(--button-bg, #fff);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  overflow: hidden;
  padding: 0;
  transition:
    transform 0.18s,
    box-shadow 0.18s;
}

.avatar-btn:hover {
  transform: scale(1.05);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);
}

.avatar-btn:focus-visible {
  outline: 3px solid var(--primary, #667eea);
  outline-offset: 2px;
}

.avatar-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}

.avatar-text {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--button-text, #667eea);
  user-select: none;
}

@media (max-width: 480px) {
  .avatar-text {
    font-size: 1.2rem;
  }
}

.pin-input {
  width: 100%;
  padding: 0.5rem 0.6rem;
  font-size: 1rem;
  border-radius: 8px;
  border: 1px solid #e6e6e6;
  margin-bottom: 0.8rem;
  box-sizing: border-box;
  text-align: center;
}

.stay-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
  color: var(--form-label, #444);
  cursor: pointer;
  margin-bottom: 1rem;
  user-select: none;
}

.stay-checkbox {
  width: 16px;
  height: 16px;
  accent-color: var(--btn-primary, #667eea);
  cursor: pointer;
  flex-shrink: 0;
}

.persistent-badge {
  position: absolute;
  bottom: -2px;
  left: -2px;
  font-size: 10px;
  line-height: 1;
  pointer-events: none;
  user-select: none;
}

.dropdown-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  background: var(--form-bg, #fff);
  border: 1px solid var(--form-input-border, #cbd5e1);
  border-radius: 12px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  min-width: 240px;
  z-index: 100;
  overflow: hidden;
}

.dropdown-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px;
  background: var(--header-bg, linear-gradient(135deg, #667eea 0%, #764ba2 100%));
  color: #fff;
}

.dropdown-avatar,
.dropdown-avatar-initial {
  width: 48px;
  height: 48px;
  min-width: 48px;
  min-height: 48px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(255, 255, 255, 0.3);
}

.dropdown-avatar-initial {
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.2);
  font-size: 1.5rem;
  font-weight: 700;
  color: #fff;
}

.dropdown-user-info {
  flex: 1;
  min-width: 0;
}

.dropdown-user-name {
  font-weight: 700;
  font-size: 1.1rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dropdown-user-email {
  font-size: 0.85rem;
  opacity: 0.9;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px 16px;
  background: transparent;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-weight: 600;
  color: var(--form-label, #444);
  font-size: 0.95rem;
  transition: background 0.15s;
}

.menu-item.focused {
  background: var(--btn-secondary-hover, #e2e8f0);
}

.menu-item:focus-visible {
  outline: 2px solid var(--primary, #667eea);
  outline-offset: -2px;
}

.menu-item.danger {
  color: var(--btn-danger, #ef4444);
}

.menu-icon-stub {
  width: 20px;
  height: 20px;
  background: var(--form-input-bg, #f8fafc);
  border-radius: 4px;
  flex-shrink: 0;
}

/* Slide fade animation */
.slide-fade-enter-active,
.slide-fade-leave-active {
  transition: all 0.2s ease;
}

.slide-fade-enter-from {
  opacity: 0;
  transform: translateY(-8px);
}

.slide-fade-leave-to {
  opacity: 0;
  transform: translateY(-8px);
}

@media (max-width: 600px) {
  .menu-item {
    padding: 12px 14px;
    font-size: 1rem;
  }

  .dropdown-menu {
    min-width: 200px;
  }
}
</style>
