// Modèle de données du générateur de portfolios (spec §7.2, gabarit_book_v3)

// --- Contenu importé de Grav (lecture seule) ---

export interface MediaVariant {
  label: `${number}x`
  path: string // chemin relatif au dossier du projet
  width?: number
}

export interface MediaAsset {
  filename: string
  type: 'image' | 'video'
  variants: MediaVariant[]
  posterPath?: string // pour les vidéos : image d'aperçu
  width?: number // dimensions de la 1re variante (images) — sert au choix
  height?: number // automatique des grilles selon l'orientation
}

export interface Project {
  id: string // ex: "01.culturelle/atlas-atterrissage"
  category: string // "culturelle" | "publique" | "sociale"
  title: string
  bodyMarkdown: string
  bodyHtml: string
  coverImage?: string // 1re image de media_order (= grille du CMS)
  media: MediaAsset[] // dans l'ordre de media_order
  categories: string[] // taxonomy.category
  tags: string[] // taxonomy.tag
  date?: string // ISO
  externalUrl?: string
  published: boolean
}

// --- Composition (créée dans l'outil, sauvegardée) ---

/** Fond de page unifié : blanc, teinté (aplat clair fixe) ou plein (couleur du
 *  filet/bandeau de la page, dérivée au rendu). */
export type Background =
  | { mode: 'white' }
  | { mode: 'tint' }
  | { mode: 'full' }

export type BgMode = Background['mode']

/** Encre du bandeau d'une page projet : auto = selon luminance du fond. */
export type InkMode = 'auto' | 'black' | 'white'

// Média résolu pour un template : URL prête à afficher (spec §9.2)
export interface ResolvedMedia {
  filename: string
  type: 'image' | 'video'
  url: string
  posterUrl?: string
  ratio?: number // largeur / hauteur intrinsèque (sert au dimensionnement des bandeaux)
  caption?: string // légende affichée sous l'image (ex. titre du projet sur les pages libres)
}

/**
 * Page « couverture » d'un projet (gabarit p.1/3/5/7) : bandeau pleine
 * largeur (titre, pastille catégorie, présentation) + image de couverture.
 */
export interface ProjectPage {
  kind: 'project'
  id: string // id de page (unique dans le portfolio)
  projectId: string
  coverImage?: string // défaut : 1re image du projet (grille CMS)
  coverFit?: 'width' | 'height' // calage de l'image — défaut : largeur
  coverAlign?: 'left' | 'center' | 'right' // calage horizontal (fit hauteur) — défaut : centrée
  titleScale?: number // taille du titre en % du gabarit (défaut 100)
  bandHeight?: number // hauteur du bandeau en mm = calage haut de l'image (défaut 55)
  subtitleOverride?: string // type du projet affiché dans la ligne d'info (ex. « édition ») — sinon rien
  subtitle?: string // sous-titre sous le titre (même fonte que le titre, plus petit)
  link?: string // lien du projet affiché sous le titre (défaut : externalUrl du projet) — actif dans le PDF et l'aperçu
  year?: string // année affichée dans la ligne d'info (défaut : année de project.date)
  background?: Background // fond : blanc / teinté (filet fin) / plein (bandeau ou colonne coloré) — défaut blanc
  layout?: 'band' | 'split' // disposition : bandeau haut (défaut) ou colonne texte + image droite
  textOverride?: string // sinon texte Grav
  bandColor?: string // défaut : couleur de la catégorie (gabarit) — définit
  // aussi la couleur des filets des pages grille du même projet
  ink?: InkMode // défaut : auto
}

/**
 * Page « grille » d'un projet (gabarit p.2/4/6/8) : filet couleur en haut,
 * images entières calées sur une grille, fond blanc.
 */
export interface ProjectGridPage {
  kind: 'project-grid'
  id: string
  projectId: string
  grid: string // id de GridDef (composables/useGrids)
  media: string[] // filenames choisis + ordonnés — images uniquement
  background?: Background // fond : blanc / teinté / plein (couleur du filet, hérité) — défaut blanc
  // Pas de couleur de filet propre : il hérite du bandeau de la page
  // couverture du même projet.
}

export type FreeColumnKind = 'text' | 'media'

/** Colonne d'une page libre : soit du texte (markdown), soit des images. */
export interface FreeColumn {
  id: string
  kind: FreeColumnKind
  heading?: string // sous-titre optionnel en tête de colonne
  body?: string // markdown (colonnes texte)
  media?: string[] // "projectId/filename" (colonnes images)
}

export interface FreePage {
  kind: 'free'
  id: string
  template: 'free-text'
  title?: string
  columns?: FreeColumn[] // 1 à 3 colonnes de texte ou d'images
  body?: string // legacy (mono-colonne texte) — migré vers columns à l'ouverture
  media?: string[] // legacy (colonne images) — migré vers columns à l'ouverture
  background: Background // blanc / teinté / plein (couleur du filet)
  bandColor?: string // filet haut optionnel
  textScale?: number // taille du texte de labeur en % (défaut 100)
}

export interface CoverPage {
  kind: 'cover'
  id: string
  background: Background // blanc / teinté / plein (couleur du filet)
  bandColor?: string // filet couleur en bas — définit aussi le filet du sommaire
}

export interface TocPage {
  kind: 'toc'
  id: string
  title?: string
  background: Background // blanc / teinté / plein (couleur du filet, héritée)
  // Pas de couleur de filet propre : il hérite du filet de la couverture.
}

/**
 * Page de conclusion : « Merci ! » en grand au centre + rappel des contacts
 * (site, mail, adresse tirés de la couverture). Bookend de la couverture.
 */
export interface OutroPage {
  kind: 'outro'
  id: string
  title?: string // texte central — défaut « Merci ! »
  background: Background // blanc / teinté / plein (couleur du filet)
  bandColor?: string // filet couleur en bas — défaut encre
}

/** Membre affiché sur la page équipe. Nom et portrait viennent du roster
 *  statique (composables/useTeam) ; rôle et présentation sont surchargeables. */
export interface TeamMemberConfig {
  id: string // référence un membre de TEAM_ROSTER
  enabled: boolean // affiché dans la grille ?
  role?: string // rôle (défaut : celui du roster)
  bio?: string // présentation (défaut : celle du roster)
}

/**
 * Page « équipe » : présente les membres du collectif en grille de 3 colonnes
 * (portrait, nom, rôle, présentation). La grille s'adapte au nombre de membres
 * cochés. Titre par défaut « L'équipe ».
 */
export interface TeamPage {
  kind: 'team'
  id: string
  title?: string // défaut « L'équipe »
  members: TeamMemberConfig[] // ordre + sélection + surcharges
  background: Background // blanc / teinté / plein (couleur du filet)
  bandColor?: string // filet couleur en haut — défaut encre
}

export type Page = ProjectPage | ProjectGridPage | FreePage | CoverPage | TocPage | OutroPage | TeamPage

export interface CoverConfig {
  title: string
  subtitle?: string
  recipient?: string // « préparé pour … »
  body?: string // texte libre (markdown) sous la phrase d'intro — plus petit, centré avec elle
  backgroundImage?: string // "projectId/filename"
  background: Background // couleur du bandeau de couverture
  date?: string // texte libre affiché dans l'en-tête de couverture (ex. « Juillet 2026 »)
  siteUrl?: string // lien du site — en-tête de couverture + header de la vue publique (défaut DEFAULT_SITE_URL)
  contactEmail?: string // mail de contact — en-tête de couverture + header public (défaut DEFAULT_CONTACT_EMAIL)
  address?: string // adresse postale — angle bas-gauche de la couverture (défaut DEFAULT_ADDRESS)
}

// Contenu figé à la génération (spec §7.3) — vrai instantané : contenu Grav
// (`projects`) **et** composition (nom, couverture, pages) au moment du gel.
// La vue publique n'affiche que cet instantané ; le PDF, lui, rend la
// composition courante. (Optionnels : instantanés antérieurs sans composition.)
export interface FrozenSnapshot {
  generatedAt: string
  fileName: string
  projects: Record<string, Project> // projets tels qu'utilisés à la génération
  name?: string // nom du portfolio figé
  cover?: CoverConfig // couverture figée
  pages?: Page[] // composition (pages + mise en forme) figée
}

export interface Portfolio {
  id: string
  name: string
  cover: CoverConfig
  pages: Page[]
  createdAt: string
  updatedAt: string
  frozenContent?: FrozenSnapshot
  lastExport?: { fileName: string; at: string }
  publicShare?: boolean // lien public /view/<id> activé (opt-in, révocable)
  showYears?: boolean // affiche l'année sur les couvertures de projet — défaut : true
}

export interface PortfolioSummary {
  id: string
  name: string
  pageCount: number
  updatedAt: string
  createdAt: string
  coverTitle: string
  hasPdf: boolean
  pdfCurrent: boolean // un PDF existe et reflète l'état courant (non modifié depuis)
  exportFileName?: string // nom du dernier PDF généré (pour téléchargement direct)
  publicShare: boolean // lien public /view/<id> actif
}
