<script setup lang="ts">
/**
 * /textes/[slug] — le document vivant : sections repliables + scroll-spy
 * (sommaire latéral desktop, dropdown mobile), clauses (pastille d'inertie
 * câblée, mini-jauge de session réelle, statut), détail dépliable, vue
 * projetée, provenance. Spécifique Pacte : valeurs en clair + effet immédiat,
 * clause d'inertie protégée, A1 en tête, préambule boussoles.
 */
import type { Clause } from '~/types/domain'
import { useCollectiveStore } from '~/stores/collective'
import { PACT_BADGE, PACT_SUBTITLE } from '~/lexicon'
import {
  buildClauseView,
  formatInt,
  liveClauseGauges,
  sectionMeta,
  type ClauseSessionGauge,
  type ClauseView,
  type ClauseViewCtx,
} from '~/components/texts/textsModel'

const route = useRoute()
const store = useCollectiveStore()

const doc = computed(() =>
  store.docs.find(d => d.slug === String(route.params.slug)) ?? null)
const isPact = computed(() => doc.value?.role === 'pact')

// ── Clauses & sections (A1 en tête : l'ordre des positions fait foi) ──
const docClauses = computed(() =>
  store.clauses
    .filter(c => c.docId === doc.value?.id)
    .sort((a, b) => a.position - b.position))

interface SectionGroup { tag: string; label: string; icon: string; clauses: Clause[] }
const sections = computed((): SectionGroup[] => {
  const groups = new Map<string, Clause[]>()
  for (const clause of docClauses.value) {
    const list = groups.get(clause.section) ?? []
    list.push(clause)
    groups.set(clause.section, list)
  }
  return [...groups.entries()].map(([tag, clauses]) => ({ tag, ...sectionMeta(tag), clauses }))
})

// ── Assemblage des vues de clauses (pur, dans textsModel) ──
const gauges = computed(() => {
  const map = new Map<string, ClauseSessionGauge>()
  for (const gauge of liveClauseGauges(docClauses.value, store.decisions, store.sessions, store.votes)) {
    map.set(gauge.clauseId, gauge)
  }
  return map
})
const viewCtx = computed((): ClauseViewCtx => ({
  versions: store.versions,
  decisions: store.decisions,
  people: store.people,
  protocols: store.protocols,
  settings: store.settings,
  gauges: gauges.value,
  isPact: isPact.value,
  memberCount: store.people.length,
}))
const viewByClause = computed(() => new Map<string, ClauseView>(
  docClauses.value.map(c => [c.id, buildClauseView(c, viewCtx.value)]),
))
function viewOf(clause: Clause): ClauseView {
  return viewByClause.value.get(clause.id) ?? buildClauseView(clause, viewCtx.value)
}

// ── Dépliage clause + repli sections ──
const expandedClauseId = ref<string | null>(null)
function toggleClause(id: string) {
  expandedClauseId.value = expandedClauseId.value === id ? null : id
}
const collapsedSections = ref<Record<string, boolean>>({})
watch(sections, (list) => {
  if (list.length > 0 && Object.keys(collapsedSections.value).length === 0) {
    const map: Record<string, boolean> = {}
    list.forEach((s, i) => { map[s.tag] = i >= 2 })
    collapsedSections.value = map
  }
}, { immediate: true })

// ── Vue projetée : le document si les votes en cours passaient ──
const projected = ref(false)
function projectedContent(clause: Clause): { content: string; changed: boolean } {
  const view = viewOf(clause)
  const proposed = view.proposed[0]
  return proposed
    ? { content: proposed.version.content, changed: true }
    : { content: view.current?.content ?? '', changed: false }
}
const projectedChanges = computed(() =>
  docClauses.value.filter(c => viewOf(c).proposed.length > 0).length)

// ── Sommaire + scroll-spy ──
const activeSection = ref<string | null>(null)
let observer: IntersectionObserver | null = null
function observeSections() {
  observer?.disconnect()
  observer = new IntersectionObserver((entries) => {
    for (const entry of entries) {
      if (entry.isIntersecting) activeSection.value = entry.target.id.replace('sec-', '')
    }
  }, { rootMargin: '-15% 0px -70% 0px' })
  for (const section of sections.value) {
    const el = document.getElementById(`sec-${section.tag}`)
    if (el) observer.observe(el)
  }
}
onMounted(() => nextTick(observeSections))
watch([sections, projected], () => nextTick(observeSections))
onUnmounted(() => observer?.disconnect())

function scrollToSection(tag: string) {
  if (collapsedSections.value[tag]) collapsedSections.value[tag] = false
  nextTick(() => {
    document.getElementById(`sec-${tag}`)?.scrollIntoView({ behavior: 'smooth', block: 'start' })
    activeSection.value = tag
  })
}
</script>

<template>
  <!-- ld-v2 -->
  <div class="doc-page">
    <NuxtLink to="/textes" class="ld-btn ld-btn--quiet doc-page__back">
      <UIcon name="i-lucide-arrow-left" />
      Tous les textes
    </NuxtLink>

    <p v-if="!doc" class="doc-page__missing">
      Ce texte est introuvable — il a peut-être été remplacé ou retiré.
    </p>

    <template v-else>
      <!-- En-tête -->
      <header class="doc-page__header">
        <div class="doc-page__badges">
          <span v-if="isPact" class="doc-page__pact-badge">{{ PACT_BADGE }}</span>
          <span v-else class="doc-page__ref-badge">document de référence</span>
        </div>
        <h1 class="doc-page__title">{{ doc.title }}</h1>
        <p class="doc-page__desc">{{ isPact ? PACT_SUBTITLE : doc.description }}</p>
        <div v-if="isPact" class="doc-page__compass">
          <UIcon name="i-lucide-compass" />
          <span>Autonomie</span><span class="doc-page__compass-dot">·</span>
          <span>Équilibre</span><span class="doc-page__compass-dot">·</span>
          <span>Liaison</span>
        </div>
        <div class="doc-page__meta">
          <span class="doc-page__meta-chip">{{ formatInt(docClauses.length) }} clauses</span>
          <span v-if="gauges.size" class="doc-page__meta-chip doc-page__meta-chip--vote">
            {{ gauges.size }} session{{ gauges.size > 1 ? 's' : '' }} en cours
          </span>
          <button
            type="button"
            class="doc-page__projected"
            :class="{ 'doc-page__projected--on': projected }"
            :disabled="projectedChanges === 0"
            :title="projectedChanges === 0 ? 'Aucune version proposée sur ce texte' : ''"
            @click="projected = !projected"
          >
            <UIcon name="i-lucide-telescope" />
            {{ projected ? 'Revenir au texte en vigueur' : 'Le document si les votes en cours passaient' }}
          </button>
        </div>
      </header>

      <div class="doc-page__body">
        <!-- Sommaire : latéral en desktop, dropdown en mobile -->
        <nav class="doc-page__toc" aria-label="Sommaire">
          <select
            class="doc-page__toc-select"
            :value="activeSection ?? ''"
            @change="scrollToSection(($event.target as HTMLSelectElement).value)"
          >
            <option value="" disabled>Aller à une section…</option>
            <option v-for="section in sections" :key="section.tag" :value="section.tag">
              {{ section.label }} ({{ section.clauses.length }})
            </option>
          </select>
          <ul class="doc-page__toc-list">
            <li v-for="section in sections" :key="section.tag">
              <button
                type="button"
                class="doc-page__toc-item"
                :class="{ 'doc-page__toc-item--active': activeSection === section.tag }"
                @click="scrollToSection(section.tag)"
              >
                <UIcon :name="section.icon" />
                <span class="doc-page__toc-label">{{ section.label }}</span>
                <span class="doc-page__toc-count">{{ section.clauses.length }}</span>
              </button>
            </li>
          </ul>
        </nav>

        <!-- Les sections -->
        <div class="doc-page__sections">
          <section
            v-for="section in sections"
            :id="`sec-${section.tag}`"
            :key="section.tag"
            class="doc-page__section"
          >
            <button
              type="button"
              class="doc-page__section-head"
              @click="collapsedSections[section.tag] = !collapsedSections[section.tag]"
            >
              <UIcon :name="section.icon" class="doc-page__section-icon" />
              <h2 class="doc-page__section-title">{{ section.label }}</h2>
              <span class="doc-page__toc-count">{{ section.clauses.length }}</span>
              <UIcon
                name="i-lucide-chevron-down"
                class="doc-page__chevron"
                :class="{ 'doc-page__chevron--open': !collapsedSections[section.tag] }"
              />
            </button>

            <div v-show="!collapsedSections[section.tag]" class="doc-page__clauses">
              <!-- Vue projetée : lecture, votes appliqués -->
              <template v-if="projected">
                <article
                  v-for="clause in section.clauses"
                  :key="clause.id"
                  class="doc-page__projected-clause"
                  :class="{ 'doc-page__projected-clause--changed': projectedContent(clause).changed }"
                >
                  <p class="doc-page__clause-head">
                    <span class="doc-page__clause-code">{{ clause.code }}</span>
                    <span class="doc-page__clause-name">{{ clause.title }}</span>
                    <span v-if="projectedContent(clause).changed" class="doc-page__changed-chip">
                      si le vote passe
                    </span>
                  </p>
                  <MarkdownRenderer
                    :content="projectedContent(clause).content"
                    class="doc-page__projected-text"
                  />
                </article>
              </template>

              <!-- Vue structurée : la boucle vote ⇒ texte -->
              <template v-else>
                <ClauseCard
                  v-for="clause in section.clauses"
                  :key="clause.id"
                  :view="viewOf(clause)"
                  :expanded="expandedClauseId === clause.id"
                  @toggle="toggleClause(clause.id)"
                />
              </template>
            </div>
          </section>

          <TextProvenance v-if="doc.provenance" :provenance="doc.provenance" />
        </div>
      </div>
    </template>
  </div>
</template>

<style scoped>
.doc-page {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  max-width: 64rem;
  margin: 0 auto;
  padding-bottom: 4rem;
}
.doc-page__back { align-self: flex-start; font-size: 0.8125rem; text-decoration: none; }
.doc-page__missing { font-size: 0.9375rem; color: var(--mood-text-muted); font-style: italic; }

.doc-page__header { display: flex; flex-direction: column; gap: 0.45rem; }
.doc-page__badges { display: flex; gap: 0.4rem; }
.doc-page__pact-badge,
.doc-page__ref-badge {
  font-size: 0.6875rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.07em; padding: 3px 10px; border-radius: var(--r-pill);
}
.doc-page__pact-badge { background: var(--mood-accent); color: var(--mood-accent-text); }
.doc-page__ref-badge {
  background: color-mix(in srgb, var(--mood-text) 7%, transparent);
  color: var(--mood-text-muted);
}
.doc-page__title {
  font-size: clamp(1.35rem, 4.5vw, 1.8rem); font-weight: 800;
  letter-spacing: -0.02em; color: var(--mood-text); line-height: 1.2;
}
.doc-page__desc { font-size: 0.875rem; color: var(--mood-text-muted); line-height: 1.55; }
.doc-page__compass {
  display: inline-flex; align-items: center; gap: 0.45rem; align-self: flex-start;
  font-size: 0.8125rem; font-weight: 700; color: var(--mood-tertiary);
  background: color-mix(in srgb, var(--mood-tertiary) 10%, transparent);
  padding: 0.3rem 0.9rem; border-radius: var(--r-pill);
}
.doc-page__compass-dot { opacity: 0.5; }

.doc-page__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem; margin-top: 0.2rem; }
.doc-page__meta-chip {
  font-size: 0.75rem; font-weight: 700; padding: 3px 10px; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--mood-text) 6%, transparent);
  color: var(--mood-text-muted);
}
.doc-page__meta-chip--vote { background: var(--mood-status-vote-bg); color: var(--mood-status-vote); }
.doc-page__projected {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.75rem; font-weight: 700; padding: 4px 12px; border-radius: var(--r-pill);
  background: var(--mood-surface); color: var(--mood-text-muted);
  box-shadow: var(--shadow-card); cursor: pointer;
}
.doc-page__projected:disabled { opacity: 0.45; cursor: not-allowed; }
.doc-page__projected--on {
  background: var(--mood-status-fige-bg); color: var(--mood-status-fige);
  box-shadow: 0 0 0 2px var(--mood-status-fige);
}

.doc-page__body { display: grid; grid-template-columns: 1fr; gap: 1.25rem; align-items: start; }
@media (min-width: 1024px) { .doc-page__body { grid-template-columns: 15rem 1fr; } }

.doc-page__toc { display: flex; flex-direction: column; gap: 0.5rem; }
.doc-page__toc-select {
  padding: 0.55rem 0.8rem;
  font-size: 0.875rem;
  font-weight: 600;
  box-shadow: inset 0 0 0 1.5px var(--mood-input-border);
}
.doc-page__toc-list { display: none; }
@media (min-width: 1024px) {
  .doc-page__toc-select { display: none; }
  .doc-page__toc { position: sticky; top: 4.5rem; }
  .doc-page__toc-list { display: flex; flex-direction: column; gap: 2px; }
}
.doc-page__toc-item {
  display: flex; align-items: center; gap: 0.5rem; width: 100%;
  padding: 0.45rem 0.7rem; border-radius: var(--r-input);
  font-size: 0.8125rem; font-weight: 600; color: var(--mood-text-muted);
  background: none; cursor: pointer; text-align: left;
}
.doc-page__toc-item:hover { background: var(--mood-accent-soft); color: var(--mood-text); }
.doc-page__toc-item--active { background: var(--mood-accent-soft); color: var(--mood-accent); font-weight: 700; }
.doc-page__toc-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.doc-page__toc-count { font-size: 0.6875rem; font-weight: 800; opacity: 0.6; }

.doc-page__sections { display: flex; flex-direction: column; gap: 1.4rem; min-width: 0; }
.doc-page__section { scroll-margin-top: 4.5rem; }
.doc-page__section-head {
  display: flex; align-items: center; gap: 0.55rem; width: 100%;
  padding: 0.5rem 0; background: none; cursor: pointer;
  box-shadow: 0 2px 0 color-mix(in srgb, var(--mood-accent) 14%, transparent);
}
.doc-page__section-icon { color: var(--mood-accent); }
.doc-page__section-title { font-size: 1rem; font-weight: 800; color: var(--mood-text); }
.doc-page__chevron { margin-left: auto; color: var(--mood-text-muted); transform: rotate(-90deg); transition: transform 0.2s ease; }
.doc-page__chevron--open { transform: rotate(0); }

.doc-page__clauses { display: flex; flex-direction: column; gap: 0.6rem; padding-top: 0.7rem; }

.doc-page__projected-clause { padding: 0.6rem 0.9rem; border-radius: var(--r-input); }
.doc-page__projected-clause--changed { background: color-mix(in srgb, var(--mood-status-fige) 8%, transparent); }
.doc-page__clause-head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.3rem; }
.doc-page__clause-code {
  font-family: monospace; font-size: 0.75rem; font-weight: 800;
  color: var(--mood-accent); background: var(--mood-accent-soft);
  padding: 2px 8px; border-radius: 7px;
}
.doc-page__clause-name { font-size: 0.9375rem; font-weight: 700; color: var(--mood-text); }
.doc-page__changed-chip {
  font-size: 0.6875rem; font-weight: 700; padding: 2px 9px; border-radius: var(--r-pill);
  background: var(--mood-status-fige-bg); color: var(--mood-status-fige);
}
.doc-page__projected-text { font-size: 0.875rem; }
</style>
