<script setup lang="ts">
// Page « grille » de projet — gabarit_book_v3 p.2/4/6/8.
// Filet couleur 5 mm en haut, images ENTIÈRES (object-contain) calées sur
// une grille ADAPTATIVE : la famille choisie se construit selon le nombre
// d'images et leur orientation. Marges 8 mm, gouttières 3,8 mm.
import type { ResolvedMedia } from '~~/types'
import type { ImageOrientation } from '~~/composables/useGrids'

const props = withDefaults(
  defineProps<{
    media: ResolvedMedia[]
    grid: string // id de famille (useGrids)
    orientation?: ImageOrientation
    category?: string
    bandColor?: string
    greyBg?: boolean
  }>(),
  { orientation: 'mixed' },
)

const def = computed(() => gridDef(props.grid, props.media.length, props.orientation))
const strip = computed(() => stripColorOf(props.category, props.bandColor))

// Métriques du canvas A3 paysage (theme.css) — zone utile hors marges 8 mm.
const MARGIN = 30.2
const GUTTER = 14.4
const AVAIL_W = 1587.4 - 2 * MARGIN // 1527 px
const AVAIL_H = 1122.5 - 2 * MARGIN // 1062,1 px

// Familles « grande image + bandeaux/file » : la colonne étroite empile ses
// images à leur HAUTEUR RÉELLE (à la largeur de colonne), si bien que les
// gouttières entre bandeaux valent exactement --fl-gutter — comme la colonne
// de la grille « pleine largeur empilées ». Si la pile dépasse la hauteur de
// page, on réduit toutes les images proportionnellement (aucun letterbox,
// images toujours entières).
const hero = computed(() => {
  const id = def.value.id
  if (id !== 'hero-left' && id !== 'hero-right') return null
  const left = id === 'hero-left'
  const b = def.value.cells.length - 1 // nombre de bandeaux/vignettes
  if (b < 1) return null

  const cols = def.value.cols
  const bigFrac = left ? cols[0] : cols[1]
  const smallFrac = left ? cols[1] : cols[0]
  const total = bigFrac + smallFrac
  // largeur de la colonne étroite (les deux colonnes se partagent la largeur
  // utile moins la gouttière qui les sépare)
  const smallW = (smallFrac / total) * (AVAIL_W - GUTTER)

  const big = left ? props.media[0] : props.media[b]
  const bandeaux = left ? props.media.slice(1, b + 1) : props.media.slice(0, b)

  const natH = bandeaux.map(m => smallW / (m.ratio && m.ratio > 0 ? m.ratio : 1.5))
  const gaps = (b - 1) * GUTTER
  const sum = natH.reduce((a, h) => a + h, 0)
  const maxH = AVAIL_H - gaps
  const k = sum > maxH ? maxH / sum : 1
  const heights = natH.map(h => h * k)

  return { left, big, bandeaux, heights, bigFrac, smallFrac }
})

const gridStyle = computed(() => ({
  gridTemplateColumns: def.value.cols.map(c => `${c}fr`).join(' '),
  gridTemplateRows: def.value.rows.map(r => `${r}fr`).join(' '),
  gap: 'var(--fl-gutter)',
}))

function cellStyle(i: number) {
  const cell = def.value.cells[i]
  if (!cell) return {}
  return {
    gridColumn: `${cell.c + 1} / span ${cell.cs ?? 1}`,
    gridRow: `${cell.r + 1} / span ${cell.rs ?? 1}`,
  }
}

/** Cale l'image sur les lignes extérieures de la grille (jamais tronquée). */
function objectPosition(i: number) {
  const cell = def.value.cells[i]
  if (!cell) return 'left top'
  const lastCol = cell.c + (cell.cs ?? 1) === def.value.cols.length
  const firstCol = cell.c === 0
  const x = firstCol && lastCol ? 'center' : lastCol ? 'right' : 'left'
  return `${x} top`
}

const items = computed(() =>
  def.value.cells.map((_, i) => props.media[i]).filter((m): m is ResolvedMedia => !!m),
)
</script>

<template>
  <div class="fl-page" :style="greyBg ? { backgroundColor: FL_BASE } : undefined">
    <!-- Filet couleur pleine largeur -->
    <div class="absolute inset-x-0 top-0" :style="{ height: 'var(--fl-strip)', backgroundColor: strip }" />

    <!-- Grande image + bandeaux/file : bandeaux à leur hauteur réelle -->
    <div v-if="hero" class="absolute flex" :style="{ inset: 'var(--fl-margin)', gap: 'var(--fl-gutter)' }">
      <!-- grande image (à gauche pour hero-left, à droite pour hero-right) -->
      <div v-if="!hero.left" class="min-h-0 min-w-0 flex flex-col" :style="{ flex: `${hero.smallFrac} 0 0`, gap: 'var(--fl-gutter)' }">
        <div v-for="(m, i) in hero.bandeaux" :key="m.filename + i" class="min-h-0 w-full" :style="{ height: `${hero.heights[i]}px` }">
          <img :src="m.url" :alt="m.filename" class="size-full object-contain">
        </div>
      </div>
      <div class="min-h-0 min-w-0" :style="{ flex: `${hero.bigFrac} 0 0` }">
        <img
          :src="hero.big.url"
          :alt="hero.big.filename"
          class="size-full object-contain"
          :style="{ objectPosition: hero.left ? 'left top' : 'right top' }"
        >
      </div>
      <div v-if="hero.left" class="min-h-0 min-w-0 flex flex-col" :style="{ flex: `${hero.smallFrac} 0 0`, gap: 'var(--fl-gutter)' }">
        <div v-for="(m, i) in hero.bandeaux" :key="m.filename + i" class="min-h-0 w-full" :style="{ height: `${hero.heights[i]}px` }">
          <img :src="m.url" :alt="m.filename" class="size-full object-contain">
        </div>
      </div>
    </div>

    <!-- Grille d'images standard dans les marges de 8 mm -->
    <div v-else class="absolute grid" :style="{ inset: 'var(--fl-margin)', ...gridStyle }">
      <div v-for="(m, i) in items" :key="m.filename + i" class="min-h-0 min-w-0" :style="cellStyle(i)">
        <img
          :src="m.url"
          :alt="m.filename"
          class="size-full object-contain"
          :style="{ objectPosition: objectPosition(i) }"
        >
      </div>
    </div>
  </div>
</template>
