<script setup lang="ts">
import { usePreferredReducedMotion, useSessionStorage } from '@vueuse/core'
import { computed, type Component, watch } from 'vue'
import type { Memory, StatusPayload } from '../api/client'
import {
  getStoryNavAccentClass,
  getStoryShellClasses,
  getStoryTransitionName,
} from '../utils/storyPageTransition'
import FirstMeetDmPage from './FirstMeetDmPage.vue'
import FirstMeetCampusPage from './FirstMeetCampusPage.vue'
import FirstCallPage from './FirstCallPage.vue'
import FirstMeetTrainPage from './FirstMeetTrainPage.vue'
import FissurePage from './FissurePage.vue'
import HeartWindowPage from './HeartWindowPage.vue'
import HomeRentalPage from './HomeRentalPage.vue'
import IkeaDatePage from './IkeaDatePage.vue'
import LaborDayPage from './LaborDayPage.vue'
import LuckinCoffeePage from './LuckinCoffeePage.vue'
import QuanjiPage from './QuanjiPage.vue'
import ReconcilePage from './ReconcilePage.vue'
import StandardNepalPage from './StandardNepalPage.vue'
import TaxiHandHoldPage from './TaxiHandHoldPage.vue'

const props = defineProps<{
  memories: Memory[]
  status: StatusPayload
}>()

const storyIndex = useSessionStorage('nj_story_idx', 0)
const reduceMotion = usePreferredReducedMotion()

watch(
  () => props.memories.length,
  (n) => {
    if (n === 0) return
    if (storyIndex.value >= n) storyIndex.value = n - 1
    if (storyIndex.value < 0) storyIndex.value = 0
  },
  { immediate: true },
)

const current = computed(() => props.memories[storyIndex.value] ?? null)

const pageComponent = computed(() => {
  const memory = current.value
  if (!memory) return StandardNepalPage

  const storyPageMap: Record<number, Component> = {
    20260420: FirstMeetDmPage,
    20260422: FirstMeetCampusPage,
    20260423: LuckinCoffeePage,
    20260424: FirstCallPage,
    20260430: FirstMeetTrainPage,
    20260431: TaxiHandHoldPage,
    20260432: QuanjiPage,
    20260501: LaborDayPage,
    20260503: FissurePage,
    20260504: ReconcilePage,
    20260508: HomeRentalPage,
    20260510: IkeaDatePage,
    20260520: HeartWindowPage,
  }

  const exactPage = storyPageMap[memory.story_order]
  if (exactPage) return exactPage

  const t = memory.unique_feature_type
  if (t === 'heart_window') return HeartWindowPage
  if (t === 'fissure_page') return FissurePage
  if (t === 'first_meet') return FirstMeetDmPage
  if (t === 'first_meet_ju') return FirstMeetCampusPage
  if (t === 'first_meet_rui') {
    return memory.event_title.includes('电话') ? FirstCallPage : LuckinCoffeePage
  }
  if (t === 'first_meet_train') return FirstMeetTrainPage
  if (t === 'first_meet_taix') return TaxiHandHoldPage
  if (t === 'first_meet_quanji') return QuanjiPage
  if (t === 'make_love') return LaborDayPage
  return StandardNepalPage
})

const transitionName = computed(() => {
  if (reduceMotion.value === 'reduce') return 'story-none'
  return getStoryTransitionName(current.value)
})

const shellChrome = computed(() => getStoryShellClasses(current.value))
const navAccent = computed(() => getStoryNavAccentClass(current.value))

function prev() {
  storyIndex.value = Math.max(0, storyIndex.value - 1)
}

function next() {
  storyIndex.value = Math.min(props.memories.length - 1, storyIndex.value + 1)
}
</script>

<template>
  <div v-if="memories.length" class="min-h-dvh">
    <div class="relative min-h-dvh">
      <div
        class="sticky top-0 z-10 flex items-center justify-between gap-2 border-b border-paper-shadow/70 bg-paper/88 px-3 py-2 backdrop-blur-md sm:px-4"
      >
        <button
          type="button"
          class="rounded-full border border-paper-shadow bg-white/90 px-3 py-1.5 text-xs text-ink shadow-sm transition disabled:opacity-40"
          :class="navAccent"
          :disabled="storyIndex <= 0"
          @click="prev"
        >
          上一页
        </button>
        <Transition mode="out-in" name="nj-title">
          <p
            v-if="current"
            :key="current.id"
            class="min-w-0 flex-1 truncate text-center text-xs text-ink-muted sm:text-sm"
          >
            <span class="font-medium text-ink">{{ current.event_title }}</span>
            <span class="mx-1 text-ink-muted">·</span>
            <span>{{ current.date }}</span>
          </p>
        </Transition>
        <button
          type="button"
          class="rounded-full border border-paper-shadow bg-white/90 px-3 py-1.5 text-xs text-ink shadow-sm transition disabled:opacity-40"
          :class="navAccent"
          :disabled="storyIndex >= memories.length - 1"
          @click="next"
        >
          下一页
        </button>
      </div>

      <div
        class="relative mx-auto max-w-3xl px-1 pb-24 pt-2 sm:px-4 sm:pb-16 sm:pt-4 [perspective:1400px]"
      >
        <div
          class="relative min-h-[60vh] overflow-hidden rounded-2xl bg-gradient-to-b from-white/70 to-lokta-cream/30 ring-1 transition-[box-shadow,border-color] duration-500 [transform-style:preserve-3d]"
          :class="shellChrome"
        >
          <div class="pointer-events-none absolute inset-0 nepal-fiber opacity-15 mix-blend-multiply" />
          <Transition :name="transitionName" mode="out-in">
            <div
              v-if="current"
              :key="current.id"
              class="relative z-[1] will-change-transform"
            >
              <component :is="pageComponent" :memory="current" />
            </div>
          </Transition>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
/* 顶栏标题轻切换 */
.nj-title-enter-active,
.nj-title-leave-active {
  transition: opacity 0.28s ease, transform 0.28s ease;
}
.nj-title-enter-from {
  opacity: 0;
  transform: translateY(6px);
}
.nj-title-leave-to {
  opacity: 0;
  transform: translateY(-5px);
}

/* 无障碍：减弱动效 */
.story-none-enter-active,
.story-none-leave-active {
  transition: opacity 0.2s ease;
}
.story-none-enter-from,
.story-none-leave-to {
  opacity: 0;
}

/* 通用时长曲线 */
.story-heart-enter-active,
.story-heart-leave-active,
.story-fissure-enter-active,
.story-fissure-leave-active,
.story-dawn-enter-active,
.story-dawn-leave-active,
.story-silk-enter-active,
.story-silk-leave-active,
.story-blush-enter-active,
.story-blush-leave-active,
.story-mint-enter-active,
.story-mint-leave-active,
.story-saffron-enter-active,
.story-saffron-leave-active,
.story-indigo-enter-active,
.story-indigo-leave-active,
.story-lotus-enter-active,
.story-lotus-leave-active,
.story-rose-enter-active,
.story-rose-leave-active,
.story-blue-enter-active,
.story-blue-leave-active,
.story-night-enter-active,
.story-night-leave-active,
.story-gold-enter-active,
.story-gold-leave-active,
.story-paper-enter-active,
.story-paper-leave-active {
  transition:
    opacity 0.52s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.52s cubic-bezier(0.22, 1, 0.36, 1),
    filter 0.52s cubic-bezier(0.22, 1, 0.36, 1),
    clip-path 0.52s cubic-bezier(0.22, 1, 0.36, 1);
}

/* 终章 · 心窗：推门而入 */
.story-heart-enter-from {
  opacity: 0;
  transform: perspective(1000px) rotateY(-16deg) scale(0.94);
  filter: blur(2px);
}
.story-heart-leave-to {
  opacity: 0;
  transform: perspective(900px) rotateY(10deg) scale(1.03);
  filter: blur(1px);
}

/* 争执 · 裂缝：向中间收拢再裂开 */
.story-fissure-enter-from {
  opacity: 0;
  clip-path: inset(0 46% 0 46%);
  transform: scale(0.94);
  filter: saturate(1.25) hue-rotate(-8deg);
}
.story-fissure-leave-to {
  opacity: 0;
  clip-path: inset(42% 0 42% 0);
  transform: scale(0.97);
  filter: saturate(0.85);
}

/* 初见 · 晨光 */
.story-dawn-enter-from {
  opacity: 0;
  transform: translateY(28px) scale(0.97);
  filter: brightness(1.2) saturate(1.08);
}
.story-dawn-leave-to {
  opacity: 0;
  transform: translateY(-18px) scale(1.02);
  filter: brightness(0.92);
}

/* 亲密页 · 被单与呼吸感 */
.story-silk-enter-from {
  opacity: 0;
  transform: translateY(20px) scale(0.96);
  filter: blur(2px) saturate(1.08);
}
.story-silk-leave-to {
  opacity: 0;
  transform: scale(1.03);
  filter: blur(1px) brightness(1.04);
}

/* 别扭 · 粉雾 */
.story-blush-enter-from {
  opacity: 0;
  transform: translateX(-18px) scale(0.98);
  filter: blur(1px) saturate(1.15);
}
.story-blush-leave-to {
  opacity: 0;
  transform: translateX(14px) scale(1.01);
  filter: saturate(0.9);
}

/* 和好 · 薄荷 */
.story-mint-enter-from {
  opacity: 0;
  transform: scale(0.94);
  filter: blur(2px) brightness(1.05);
}
.story-mint-leave-to {
  opacity: 0;
  transform: scale(1.04);
  filter: blur(1px);
}

/* 小家 · 姜黄暖调 */
.story-saffron-enter-from {
  opacity: 0;
  transform: translate(12px, 16px) scale(0.96) rotate(-0.8deg);
  filter: brightness(1.08);
}
.story-saffron-leave-to {
  opacity: 0;
  transform: translate(-10px, -12px) scale(1.02) rotate(0.6deg);
}

/* 宜家 · 靛蓝利落 */
.story-indigo-enter-from {
  opacity: 0;
  transform: translateX(22px) skewX(-2deg) scale(0.97);
  filter: contrast(1.05);
}
.story-indigo-leave-to {
  opacity: 0;
  transform: translateX(-18px) skewX(1.5deg);
}

/* 莲花瓣 */
.story-lotus-enter-from {
  opacity: 0;
  transform: scale(0.92) rotate(-1.2deg);
  filter: saturate(1.2) brightness(1.06);
}
.story-lotus-leave-to {
  opacity: 0;
  transform: scale(1.05) rotate(1deg);
}

/* 曼陀罗 / 玫瑰螺旋 */
.story-rose-enter-from {
  opacity: 0;
  transform: rotate(-3deg) scale(0.95);
  filter: saturate(1.18);
}
.story-rose-leave-to {
  opacity: 0;
  transform: rotate(2deg) scale(1.02);
}

/* 青蓝系 */
.story-blue-enter-from {
  opacity: 0;
  transform: translateY(20px) scale(0.97);
  filter: hue-rotate(12deg) saturate(1.1);
}
.story-blue-leave-to {
  opacity: 0;
  transform: translateY(-12px);
  filter: hue-rotate(-6deg);
}

/* 夜空 */
.story-night-enter-from {
  opacity: 0;
  transform: scale(1.06);
  filter: brightness(0.75) blur(2px);
}
.story-night-leave-to {
  opacity: 0;
  transform: scale(0.94);
  filter: brightness(1.15);
}

/* 金缮手工纸 */
.story-gold-enter-from {
  opacity: 0;
  transform: translateY(12px) rotate(1deg) scale(0.97);
  filter: sepia(0.15) brightness(1.05);
}
.story-gold-leave-to {
  opacity: 0;
  transform: translateY(-8px) rotate(-0.8deg);
}

/* 默认纸页 */
.story-paper-enter-from {
  opacity: 0;
  transform: rotateY(-10deg) translateZ(-14px);
}
.story-paper-leave-to {
  opacity: 0;
  transform: rotateY(8deg) translateZ(-8px);
}
</style>
