<script setup lang="ts">
import { Head } from '@inertiajs/vue3';
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
import UserLayout from '@/layouts/user/userlayout.vue';

const props = withDefaults(defineProps<{
  title: string;
  updated?: string;
  intro?: string;
  metaDescription?: string;
}>(), {
  intro: '',
  metaDescription: ''
});

const contentRef = ref<HTMLElement | null>(null);
const toc = ref<{ id: string; text: string; level: number }[]>([]);
const activeId = ref<string>('');
const canonical = ref<string>('');
let observer: IntersectionObserver | null = null;

function slugify(text: string): string {
  return text
    .toLowerCase()
    .normalize('NFD').replace(/\p{Diacritic}/gu, '')
    .replace(/[^a-z0-9\s-]/g, '')
    .trim().replace(/\s+/g, '-').replace(/-+/g, '-');
}

function buildToc() {
  if (!contentRef.value) return;
  toc.value = [];
  const headings = Array.from(contentRef.value.querySelectorAll('h2, h3')) as HTMLElement[];
  for (const h of headings) {
    if (!h.id) {
      h.id = slugify(h.innerText || h.textContent || 'section');
    }
    // Ensure scroll margin for sticky headers
    h.style.scrollMarginTop = '90px';
    toc.value.push({ id: h.id, text: h.innerText || h.textContent || '', level: h.tagName === 'H2' ? 2 : 3 });
  }
}

function setupObserver() {
  if (!contentRef.value) return;
  cleanupObserver();
  observer = new IntersectionObserver((entries) => {
    for (const entry of entries) {
      if (entry.isIntersecting) {
        const id = (entry.target as HTMLElement).id;
        activeId.value = id;
        break;
      }
    }
  }, { root: null, rootMargin: '0px 0px -70% 0px', threshold: [0, 1.0] });

  contentRef.value.querySelectorAll('h2, h3').forEach(el => observer!.observe(el));
}

function cleanupObserver() {
  if (observer) { observer.disconnect(); observer = null; }
}

function scrollToId(id: string) {
  const el = document.getElementById(id);
  if (!el) return;
  const top = el.getBoundingClientRect().top + window.scrollY - 80; // offset for sticky header
  window.scrollTo({ top, behavior: 'smooth' });
}

onMounted(async () => {
  await nextTick();
  buildToc();
  setupObserver();
  // compute canonical on client only to avoid SSR/window issues
  try {
    if (typeof window !== 'undefined' && window?.location) {
      canonical.value = window.location.origin + window.location.pathname;
    }
  } catch {}
  // Rebuild if icons/fonts change layout slightly
  setTimeout(buildToc, 50);
});

onBeforeUnmount(() => cleanupObserver());
</script>

<template>
  <UserLayout>
    <Head :title="props.title">
      <template #default>
        <meta v-if="props.metaDescription" name="description" :content="props.metaDescription" />
        <link v-if="canonical" rel="canonical" :href="canonical" />
      </template>
    </Head>

    <section class="policy-wrap">
      <div class="policy-grid">
        <!-- Desktop Sticky ToC -->
        <nav class="toc" :aria-label="$t('policy.toc')">
          <div class="toc-title">{{ $t('policy.toc') }}</div>
          <ul>
            <li v-for="item in toc" :key="item.id" :class="['lvl'+item.level, { active: activeId===item.id }]">
              <a :href="`#${item.id}`" @click.prevent="scrollToId(item.id)">{{ item.text }}</a>
            </li>
          </ul>
        </nav>

        <div class="policy-card">
          <header class="p-head">
            <h1 class="p-title">{{ props.title }}</h1>
            <div class="p-updated" v-if="props.updated">{{ $t('policy.lastUpdated') }}: {{ new Date(props.updated).toLocaleDateString() }}</div>
            <p v-if="props.intro" class="p-intro">{{ props.intro }}</p>

            <!-- Mobile ToC toggle -->
            <details class="toc-mobile">
              <summary>{{ $t('policy.toc') }}</summary>
              <ul>
                <li v-for="item in toc" :key="item.id" :class="['lvl'+item.level, { active: activeId===item.id }]">
                  <a :href="`#${item.id}`" @click.prevent="scrollToId(item.id)">{{ item.text }}</a>
                </li>
              </ul>
            </details>
          </header>

          <div class="p-body" ref="contentRef">
            <slot />
          </div>
        </div>
      </div>
    </section>
  </UserLayout>
</template>

<style scoped>
.policy-wrap { padding: 30px; display: flex; justify-content: center; }
.policy-grid { width: 100%; max-width: 1100px; display: grid; grid-template-columns: 260px 1fr; gap: 20px; }

/* ToC Desktop */
.toc { position: sticky; top: 90px; align-self: start; background: #0a0a0a; border: 1px solid #151515; border-radius: 12px; padding: 14px; height: fit-content; display: none; }
.toc-title { font-size: 12px; font-weight: 900; color: #fff; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px; }
.toc ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 6px; }
.toc li a { color: #aaa; text-decoration: none; font-size: 12px; font-weight: 700; display: block; padding: 6px 8px; border-radius: 8px; }
.toc li a:hover, .toc li.active a { color: #fff; background: rgba(0,242,255,0.06); }
.toc li.lvl3 a { padding-left: 18px; font-weight: 600; }

/* Show ToC on desktop */
@media (min-width: 1000px) { .toc { display: block; } }

/* Card */
.policy-card { width: 100%; background: #0a0a0a; border: 1px solid #151515; border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.6); overflow:hidden; }
.p-head { padding: 22px 26px; border-bottom: 1px solid #151515; background: linear-gradient(90deg, rgba(0,242,255,0.05), transparent); }
.p-title { margin: 0; font-size: 24px; font-weight: 900; letter-spacing: 1px; text-transform: uppercase; }
.p-updated { margin-top: 6px; font-size: 12px; color: #777; }
.p-intro { margin-top: 10px; font-size: 13px; color: #bbb; }

/* Mobile ToC */
.toc-mobile { display: block; margin-top: 12px; }
.toc-mobile > summary { cursor: pointer; list-style: none; background: #0a0a0a; border: 1px solid #1a1a1a; color: #fff; padding: 8px 10px; border-radius: 8px; font-size: 12px; font-weight: 900; }
.toc-mobile[open] > summary { background: #121212; }
.toc-mobile ul { list-style: none; padding: 8px; margin: 6px 0 0; display: grid; gap: 6px; border: 1px solid #1a1a1a; border-radius: 10px; }
.toc-mobile li a { color: #aaa; text-decoration: none; font-size: 12px; font-weight: 700; display: block; padding: 6px 8px; border-radius: 8px; }
.toc-mobile li a:hover, .toc-mobile li.active a { color: #fff; background: rgba(0,242,255,0.06); }
.toc-mobile li.lvl3 a { padding-left: 18px; font-weight: 600; }

/* Body */
.p-body { padding: 24px 26px; display: grid; gap: 18px; color: #bbb; line-height: 1.8; }
.p-body h2 { color: #fff; font-size: 18px; font-weight: 900; margin: 24px 0 6px; }
.p-body h3 { color: #ddd; font-size: 15px; font-weight: 800; margin: 14px 0 4px; }
.p-body p, .p-body li { font-size: 13px; }
.p-body ul { padding-left: 18px; list-style: disc; }
.callout { background:#0e0e0e; border:1px solid #1f1f1f; padding:12px 14px; border-radius:10px; color:#9bd; }

/* Print */
@media print {
  :host, .policy-wrap, .policy-grid, .policy-card, .p-body { all: unset; display: block; }
  .toc, .toc-mobile, .p-intro { display: none !important; }
  body { color: #000; }
  a[href]::after { content: " (" attr(href) ")"; font-size: 10px; }
}
</style>
