<script setup lang="ts">
// Vue publique d'un portfolio partagé (bouton « Partager un lien public »).
// Hors mot de passe (middleware auth exempte /view). Rendu identique au viewer
// (pages A3 mises à l'échelle) mais sans édition : header + sommaire repliable
// (masqué par défaut, suit la page active au scroll via usePageScrollSpy), et
// rien d'autre.
import type { Page, Portfolio, Project } from '~~/types'

definePageMeta({ layout: false })

const route = useRoute()
const id = String(route.params.id)

const { data } = await useFetch(`/api/public/${id}`)
if (!data.value) {
  throw createError({ statusCode: 404, statusMessage: 'Portfolio introuvable' })
}
const portfolio = computed<Portfolio>(() => data.value!.portfolio)
const projects = computed<Record<string, Project>>(() => data.value!.projects)

// Les médias passent par la route publique dédiée (snapshot figé).
const mediaBase = `/api/public/${id}/media`

// ---- Header ----
const siteUrl = computed(() => portfolio.value.cover.siteUrl?.trim() || DEFAULT_SITE_URL)
const siteLabel = computed(() => siteUrl.value.replace(/^https?:\/\//, '').replace(/\/$/, ''))
const contactEmail = computed(() => portfolio.value.cover.contactEmail?.trim() || DEFAULT_CONTACT_EMAIL)
const dateLabel = computed(() => {
  const iso = portfolio.value.frozenContent?.generatedAt ?? portfolio.value.lastExport?.at
  return iso ? new Intl.DateTimeFormat('fr-FR', { dateStyle: 'long' }).format(new Date(iso)) : ''
})

useHead({ title: () => portfolio.value.cover.title || portfolio.value.name })

// ---- Sommaire repliable + page active (scroll-spy) ----
const showSommaire = ref(false)
const activeId = ref<string | undefined>(portfolio.value.pages[0]?.id)
const previewScroll = ref<HTMLElement>()

const { onScroll, scrollToId } = usePageScrollSpy({
  container: previewScroll,
  pages: computed(() => portfolio.value.pages),
  active: activeId,
  idPrefix: 'view-page',
})

function pageLabel(page: Page): string {
  switch (page.kind) {
    case 'cover': return portfolio.value.cover.title || 'Couverture'
    case 'toc': return page.title || 'Sommaire'
    case 'free': return page.title || 'Page libre'
    case 'project':
    case 'project-grid': return projects.value[page.projectId]?.title ?? page.projectId
    case 'outro': return page.title || 'Conclusion'
    case 'team': return page.title || 'Équipe'
  }
}
</script>

<template>
  <div class="flex h-screen flex-col bg-neutral-200/70 dark:bg-neutral-950">
    <!-- Header public -->
    <header class="flex items-center gap-3 border-b border-neutral-200 bg-white px-4 py-2.5 dark:border-neutral-800 dark:bg-neutral-900">
      <UButton
        :icon="showSommaire ? 'i-lucide-panel-left-close' : 'i-lucide-panel-left-open'"
        color="neutral"
        variant="ghost"
        size="sm"
        :aria-label="showSommaire ? 'Masquer le sommaire' : 'Afficher le sommaire'"
        @click="showSommaire = !showSommaire"
      />
      <div class="min-w-0">
        <h1 class="truncate font-semibold leading-tight">{{ portfolio.cover.title || portfolio.name }}</h1>
        <p v-if="dateLabel" class="text-xs text-neutral-500">{{ dateLabel }}</p>
      </div>
      <div class="ml-auto flex items-center gap-4 text-sm">
        <a :href="siteUrl" target="_blank" rel="noopener" class="text-neutral-600 hover:underline dark:text-neutral-300">{{ siteLabel }}</a>
        <a :href="`mailto:${contactEmail}`" class="text-neutral-600 hover:underline dark:text-neutral-300">{{ contactEmail }}</a>
      </div>
    </header>

    <div class="flex min-h-0 flex-1">
      <!-- Sommaire repliable (masqué par défaut) -->
      <aside
        v-if="showSommaire"
        class="w-60 shrink-0 space-y-0.5 overflow-y-auto border-r border-neutral-200 bg-white p-2 dark:border-neutral-800 dark:bg-neutral-900"
      >
        <button
          v-for="(page, i) in portfolio.pages"
          :key="page.id"
          type="button"
          class="flex w-full items-center gap-2 rounded-md p-2 text-left text-sm transition-colors"
          :class="page.id === activeId
            ? 'bg-neutral-100 font-medium dark:bg-neutral-800'
            : 'hover:bg-neutral-50 dark:hover:bg-neutral-800/60'"
          @click="scrollToId(page.id)"
        >
          <span class="w-5 shrink-0 text-right text-neutral-400">{{ i + 1 }}</span>
          <span class="truncate">{{ pageLabel(page) }}</span>
        </button>
      </aside>

      <!-- Pages empilées (sans liseré autour de la page active) -->
      <main
        ref="previewScroll"
        class="flex min-w-0 flex-1 flex-col items-center gap-6 overflow-auto scroll-smooth p-8"
        @scroll="onScroll"
      >
        <div
          v-for="(page, i) in portfolio.pages"
          :id="`view-page-${i + 1}`"
          :key="page.id"
          class="w-full max-w-[1180px] scroll-mt-8 rounded-sm shadow-xl"
        >
          <PageViewport>
            <PageRenderer
              :portfolio="portfolio"
              :page="page"
              :index="i"
              :projects="projects"
              render-mode="preview"
              :media-base="mediaBase"
              @navigate="(n: number) => scrollToId(portfolio.pages[n - 1]?.id ?? '')"
            />
          </PageViewport>
        </div>
      </main>
    </div>
  </div>
</template>
