<template>
  <div class="fc-reader">
    <div class="fc-reader__progress" :style="{ width: progress + '%' }" />

    <div class="fc-reader__header" :class="{ hidden: headerHidden }">
      <div class="fc-reader__hleft">
        <v-btn
          icon="mdi-arrow-left" variant="text" size="small"
          title="Back to series" @click="goBack"
        />
        <span class="fc-reader__title">
          {{ store.series?.name || 'Series' }}
        </span>
        <span class="fc-reader__count">{{ store.pages.length }} pages</span>
      </div>
      <div class="fc-reader__hright">
        <label class="fc-reader__jlabel" for="fc-reader-jump">Jump</label>
        <select
          id="fc-reader-jump" class="fc-reader__jump"
          :value="currentPage" @change="jumpTo($event.target.value)"
        >
          <option
            v-for="p in store.pages" :key="p.page_number"
            :value="p.page_number"
          >Page {{ p.page_number }}</option>
        </select>
        <v-btn
          icon="mdi-menu" variant="text" size="small"
          title="Toggle pages" @click="navOpen = !navOpen"
        />
      </div>
    </div>

    <aside class="fc-reader__nav" :class="{ open: navOpen }">
      <div class="fc-reader__navhead">
        <span>Pages</span>
        <v-btn
          icon="mdi-close" variant="text" size="x-small"
          @click="navOpen = false"
        />
      </div>
      <div class="fc-reader__thumbs">
        <div
          v-for="p in store.pages" :key="p.image_id"
          class="fc-reader__thumb"
          :class="{ active: p.page_number === currentPage }"
          @click="jumpTo(p.page_number, true)"
        >
          <img :src="p.thumbnail_url" alt="" loading="lazy" />
          <span class="fc-reader__thumbnum">{{ p.page_number }}</span>
        </div>
      </div>
    </aside>

    <div ref="scrollEl" class="fc-reader__content" @scroll="onScroll">
      <div
        v-for="p in store.pages" :key="p.image_id"
        class="fc-reader__page" :id="'fc-page-' + p.page_number"
        :data-page="p.page_number"
      >
        <img :src="p.image_url" :alt="'Page ' + p.page_number" loading="lazy" />
      </div>
      <div v-if="store.error" class="fc-reader__empty">
        {{ store.error }}
        <v-btn variant="text" color="accent" @click="goBack">Back</v-btn>
      </div>
      <div
        v-else-if="!store.loading && store.pages.length === 0"
        class="fc-reader__empty"
      >
        No pages in this series yet.
        <v-btn variant="text" color="accent" @click="goBack">Back</v-btn>
      </div>
    </div>

    <div class="fc-reader__indicator">
      {{ currentPage }} / {{ store.pages.length }}
    </div>
    <div class="fc-reader__quick">
      <v-btn size="small" variant="tonal" @click="scrollEnd(false)">↑ First</v-btn>
      <v-btn size="small" variant="tonal" @click="scrollEnd(true)">Last ↓</v-btn>
    </div>
  </div>
</template>

<script setup>
import { onMounted, onUnmounted, ref, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import {
  useSeriesReaderStore,
  currentPageFromScroll,
  progressPct,
  clampPage
} from '../stores/seriesReader.js'

const route = useRoute()
const router = useRouter()
const store = useSeriesReaderStore()

const scrollEl = ref(null)
const currentPage = ref(1)
const progress = ref(0)
const navOpen = ref(false)
const headerHidden = ref(false)

let hideTimer = null
let scrollGate = null
const tagId = parseInt(route.params.tagId, 10)

function goBack() {
  router.push({ name: 'series-manage', params: { tagId } })
}

function pageMetrics() {
  const root = scrollEl.value
  if (!root) return []
  return store.pages.map(p => {
    const el = root.querySelector('#fc-page-' + p.page_number)
    return {
      page_number: p.page_number,
      top: el ? el.offsetTop : 0,
      height: el ? el.offsetHeight : 0
    }
  })
}

function showHeader() {
  headerHidden.value = false
  clearTimeout(hideTimer)
  hideTimer = setTimeout(() => { headerHidden.value = true }, 2500)
}

function syncFromScroll() {
  const root = scrollEl.value
  if (!root) return
  progress.value = progressPct(
    root.scrollTop, root.scrollHeight, root.clientHeight
  )
  const pg = currentPageFromScroll(
    pageMetrics(), root.scrollTop, root.clientHeight
  )
  if (pg !== currentPage.value) {
    currentPage.value = pg
    const url = new URL(window.location)
    url.searchParams.set('page', String(pg))
    history.replaceState({}, '', url)
  }
}

function onScroll() {
  showHeader()
  if (scrollGate) return
  scrollGate = setTimeout(() => { syncFromScroll(); scrollGate = null }, 50)
}

function scrollToPage(n, smooth = true) {
  const el = scrollEl.value?.querySelector('#fc-page-' + n)
  if (el) el.scrollIntoView({ behavior: smooth ? 'smooth' : 'auto' })
}

function jumpTo(n, fromThumb = false) {
  scrollToPage(parseInt(n, 10), true)
  if (fromThumb && window.innerWidth < 768) navOpen.value = false
}

function scrollEnd(toBottom) {
  const root = scrollEl.value
  if (!root) return
  root.scrollTo({
    top: toBottom ? root.scrollHeight : 0, behavior: 'smooth'
  })
}

function onKey(e) {
  if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT') return
  const root = scrollEl.value
  if (!root) return
  showHeader()
  switch (e.key) {
    case 'Home': e.preventDefault(); root.scrollTo({ top: 0, behavior: 'smooth' }); break
    case 'End': e.preventDefault(); root.scrollTo({ top: root.scrollHeight, behavior: 'smooth' }); break
    case 'PageUp': e.preventDefault(); root.scrollBy({ top: -root.clientHeight * 0.9, behavior: 'smooth' }); break
    case 'PageDown':
    case ' ': e.preventDefault(); root.scrollBy({ top: root.clientHeight * 0.9, behavior: 'smooth' }); break
    case 'n': navOpen.value = !navOpen.value; break
  }
}

onMounted(async () => {
  await store.load(tagId)
  await nextTick()
  const want = clampPage(
    parseInt(route.query.page, 10), store.pages.length
  )
  if (want > 1) scrollToPage(want, false)
  currentPage.value = want
  syncFromScroll()
  showHeader()
  document.addEventListener('keydown', onKey)
  document.addEventListener('mousemove', showHeader)
})
onUnmounted(() => {
  clearTimeout(hideTimer)
  clearTimeout(scrollGate)
  document.removeEventListener('keydown', onKey)
  document.removeEventListener('mousemove', showHeader)
})
</script>

<style scoped>
.fc-reader {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  background: rgb(var(--v-theme-background));
}
.fc-reader__progress {
  position: fixed; top: 0; left: 0; height: 2px;
  background: rgb(var(--v-theme-accent));
  z-index: 1100; transition: width 0.1s linear; pointer-events: none;
}
.fc-reader__header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.5rem 0.75rem;
  background: rgb(var(--v-theme-surface));
  border-bottom: 1px solid rgb(var(--v-theme-surface-light));
  flex-shrink: 0;
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.fc-reader__header.hidden {
  opacity: 0; pointer-events: none; transform: translateY(-4px);
}
.fc-reader__hleft, .fc-reader__hright {
  display: flex; align-items: center; gap: 0.6rem;
}
.fc-reader__title {
  font-family: 'Fraunces', Georgia, serif; font-size: 1.05rem;
}
.fc-reader__count, .fc-reader__jlabel {
  font-size: 0.8rem; color: rgb(var(--v-theme-on-surface-variant));
}
.fc-reader__jump {
  padding: 0.3rem 0.5rem; border-radius: 6px;
  background: rgb(var(--v-theme-surface-light));
  color: rgb(var(--v-theme-on-surface));
  border: 1px solid rgb(var(--v-theme-surface-light));
}
.fc-reader__nav {
  position: fixed; top: 0; left: 0; width: 200px; height: 100vh;
  background: rgb(var(--v-theme-surface));
  border-right: 1px solid rgb(var(--v-theme-surface-light));
  transform: translateX(-100%); transition: transform 0.3s ease;
  z-index: 1000; display: flex; flex-direction: column;
}
.fc-reader__nav.open { transform: translateX(0); }
.fc-reader__navhead {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.75rem; border-bottom: 1px solid rgb(var(--v-theme-surface-light));
}
.fc-reader__thumbs {
  flex: 1; overflow-y: auto; padding: 0.5rem;
  display: flex; flex-direction: column; gap: 0.5rem;
}
.fc-reader__thumb {
  position: relative; border-radius: 6px; overflow: hidden;
  cursor: pointer; opacity: 0.5; transition: opacity 0.2s ease;
  outline: 2px solid transparent;
}
.fc-reader__thumb:hover { opacity: 1; }
.fc-reader__thumb.active {
  opacity: 1; outline-color: rgb(var(--v-theme-accent));
}
.fc-reader__thumb img { width: 100%; height: auto; display: block; }
.fc-reader__thumbnum {
  position: absolute; bottom: 4px; right: 4px;
  background: rgba(20, 23, 26, 0.8); color: rgb(var(--v-theme-on-surface));
  padding: 1px 5px; border-radius: 4px; font-size: 0.7rem;
}
.fc-reader__content {
  flex: 1; overflow-y: auto; scroll-behavior: smooth;
  display: flex; flex-direction: column; align-items: center;
  gap: 2px; padding: 0.25rem;
}
.fc-reader__page { width: 100%; display: flex; justify-content: center; }
.fc-reader__page img {
  max-width: min(100%, 1200px); height: auto; display: block;
}
.fc-reader__empty {
  padding: 4rem 1rem; text-align: center;
  color: rgb(var(--v-theme-on-surface-variant));
}
.fc-reader__indicator {
  position: fixed; bottom: 1.5rem; right: 1.5rem;
  padding: 4px 10px; border-radius: 999px;
  background: rgba(20, 23, 26, 0.6);
  border: 1px solid rgb(var(--v-theme-surface-light));
  font-size: 0.8rem; color: rgb(var(--v-theme-on-surface-variant));
  z-index: 100; pointer-events: none;
}
.fc-reader__quick {
  position: fixed; bottom: 1.5rem; left: 1.5rem;
  display: flex; gap: 0.5rem; z-index: 50;
}
@media (max-width: 768px) {
  .fc-reader__nav { width: 150px; }
  .fc-reader__quick { flex-direction: column; }
}
</style>
