// Adaptateurs origine — famille "produits" (4 pages produit).
//
// Chaque adaptateur reçoit une section WordPress (champs camelCase GraphQL,
// cf. src/lib/wp/types.ts) et rend le composant ORIGINAL du site en mappant
// les champs. Valeur WP absente/null => prop undefined (le défaut du composant
// d'origine prend le relais). Quand un champ WP "riche" (strong, liens…) est
// identique au contenu seedé (comparaison normalisée), on laisse volontairement
// le défaut JSX riche de l'original s'appliquer pour garder la parité pixel.
//
// Clés du registry : nom du fichier composant original, suffixé par le produit
// quand le composant générique est configuré différemment par vue
// (ex. "ProductHeroCovaTherm", "CompatibilityTabsCovaSeal").
import { Fragment } from "react";
import type { ComponentType, ReactNode } from "react";
import { sanitizeWpHtml } from "@/lib/sanitizeHtml";
import {
  BadgeCheck,
  Banknote,
  Brain,
  Building2,
  Clock,
  Droplets,
  Eye,
  FileCheck2,
  Flame,
  Heart,
  Leaf,
  Shield,
  ShieldCheck,
  Snowflake,
  Sun,
  Thermometer,
  Zap,
} from "lucide-react";
import type { LucideIcon } from "lucide-react";

import { arr, mapImage, parseAccent } from "@/lib/wp/mappers";
import { useAccentColor } from "@/components/blocks/accentContext";
import type {
  AvantApresBlock,
  CertificationsBlock,
  CompatibiliteSupportsBlock,
  ContenuSeoBlock,
  FaqBlock,
  GrilleCardsBlock,
  GrilleSolutionsBlock,
  HeroBlock,
  SpecsTechniquesBlock,
  TableauComparatifBlock,
  TexteImageBlock,
  VariantesProduitBlock,
} from "@/lib/wp/types";

import ProductHero from "@/components/product/ProductHero";
import ProductShowcase, { defaultVariants } from "@/components/product/ProductShowcase";
import CompatibilityTabs from "@/components/product/CompatibilityTabs";
import TechnicalSpecs from "@/components/product/TechnicalSpecs";
import ProductAdvantages from "@/components/product/ProductAdvantages";
import ProductFAQ from "@/components/product/ProductFAQ";
import CoolRoofGuide from "@/components/product/CoolRoofGuide";
import RelatedProducts, { allProducts } from "@/components/product/RelatedProducts";
import type { RelatedProductItem } from "@/components/product/RelatedProducts";

import CovaSealShowcase from "@/components/product/covaseal/CovaSealShowcase";
import CovaSealSpecs from "@/components/product/covaseal/CovaSealSpecs";
import CovaSealCertifications from "@/components/product/covaseal/CovaSealCertifications";
import CovaSealAdvantages from "@/components/product/covaseal/CovaSealAdvantages";
import CovaSealComparison from "@/components/product/covaseal/CovaSealComparison";
import CovaSealEditorial from "@/components/product/covaseal/CovaSealEditorial";

import CovaMetalShowcase from "@/components/product/covametal/CovaMetalShowcase";
import CovaMetalSpecs from "@/components/product/covametal/CovaMetalSpecs";
import CovaMetalCertifications from "@/components/product/covametal/CovaMetalCertifications";
import CovaMetalAdvantages from "@/components/product/covametal/CovaMetalAdvantages";
import CovaMetalComparison from "@/components/product/covametal/CovaMetalComparison";
import CovaMetalEditorial from "@/components/product/covametal/CovaMetalEditorial";

import CovaThermLightShowcase from "@/components/product/covatherm-light/CovaThermLightShowcase";
import CovaThermLightBeforeAfter from "@/components/product/covatherm-light/CovaThermLightBeforeAfter";
import CovaThermLightSpecs from "@/components/product/covatherm-light/CovaThermLightSpecs";
import CovaThermLightCertifications from "@/components/product/covatherm-light/CovaThermLightCertifications";
import CovaThermLightAdvantages from "@/components/product/covatherm-light/CovaThermLightAdvantages";
import CovaThermLightComparison from "@/components/product/covatherm-light/CovaThermLightComparison";
import CovaThermLightEditorial from "@/components/product/covatherm-light/CovaThermLightEditorial";

import {
  covathermFaqs,
  covathermLightFaqs,
  covasealFaqs,
  covametalFaqs,
} from "@/data/productFaqs";
import type { ProductFaqEntry } from "@/data/productFaqs";

// Assets de fallback (identiques aux imports des vues d'origine)
import covathermHero from "@/assets/produits/covatherm-hero.webp";
import covathermLightHero from "@/assets/produits/covatherm-light-hero.webp";
import covasealHero from "@/assets/produits/covaseal-hero.webp";
import covametalHero from "@/assets/produits/covametal-hero.webp";
import compatBitume from "@/assets/produits/compat-bitume.webp";
import compatBeton from "@/assets/produits/compat-beton.webp";
import compatEpdm from "@/assets/produits/compat-epdm.webp";
import compatFibrociment from "@/assets/produits/compat-fibrociment.webp";
import compatArdoise from "@/assets/produits/compat-ardoise.webp";
import compatPvc from "@/assets/produits/compat-pvc.webp";
import compatTuile from "@/assets/produits/compat-tuile.webp";
import compatPolycarbonate from "@/assets/produits/compat-polycarbonate.webp";
import compatPolyester from "@/assets/produits/compat-polyester.webp";
import compatFibreVerre from "@/assets/produits/compat-fibre-verre.webp";
import compatVitrage from "@/assets/produits/compat-vitrage.webp";
import compatBacAcier from "@/assets/produits/compat-bac-acier.webp";
import compatToleOndulee from "@/assets/produits/compat-tole-ondulee.webp";
import compatZinc from "@/assets/produits/compat-zinc.webp";
import compatMetalGenerique from "@/assets/produits/compat-metal-generique.webp";

type Section<T> = T & { position?: number };

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

/** Normalise un texte WP (tags HTML, entités, espaces) pour comparaison. */
function norm(s: string): string {
  return s
    .replace(/&nbsp;/g, " ")
    .replace(/&rsquo;|&#8217;|’/g, "'") // apostrophe wptexturize -> droite (seed)
    .replace(/&amp;/g, "&")
    .replace(/<[^>]+>/g, " ")
    .replace(/\s+/g, " ")
    .trim();
}

/** Hash djb2 (mêmes valeurs que le calcul de référence sur les seeds). */
function hash(s: string): number {
  let h = 5381;
  for (let i = 0; i < s.length; i++) {
    h = ((h * 33) ^ s.charCodeAt(i)) >>> 0;
  }
  return h;
}

/**
 * Retourne la valeur WP, ou undefined si elle est vide ou identique
 * (après normalisation) au contenu d'origine — le défaut riche du composant
 * (strong, liens stylés…) prend alors le relais.
 */
function richOr(value: string | null | undefined, normalizedDefault: string): string | undefined {
  if (!value) return undefined;
  return norm(value) === normalizedDefault ? undefined : value;
}

/** Supprime le <p> englobant d'un wysiwyg mono-paragraphe. */
function stripOuterP(html: string): string {
  return html.trim().replace(/^<p>/i, "").replace(/<\/p>$/i, "");
}

/**
 * Reconstruit le markup de titre des originaux à partir de la convention
 * `*accent*` : segment accentué => <span className={accentClass}>, précédé
 * d'un <br /> (sauf opts.br === false, pour les titres dont le span est sur
 * la même ligne).
 */
function accentNode(
  titre: string | null | undefined,
  accentClass: string,
  opts: { br?: boolean } = {},
): ReactNode | undefined {
  if (!titre) return undefined;
  const segments = parseAccent(titre);
  if (!segments.some((s) => s.accent)) return titre;
  return (
    <>
      {segments.map((seg, i) =>
        seg.accent ? (
          <Fragment key={i}>
            {opts.br !== false && i > 0 && <br />}
            <span className={accentClass}>{seg.text}</span>
          </Fragment>
        ) : (
          <Fragment key={i}>{seg.text}</Fragment>
        ),
      )}
    </>
  );
}

/** Cellule de tableau specs : "oui"/"non"/"-" => boolean/null, sinon texte. */
function cellValue(t: string | null | undefined): string | boolean | null {
  if (t == null) return null;
  const v = t.trim();
  if (v === "" || v === "-") return null;
  if (v.toLowerCase() === "oui") return true;
  if (v.toLowerCase() === "non") return false;
  return t;
}

/** Icônes des cards `grille_cards` (slug WP -> icône lucide de l'original). */
const CARD_ICONS: Record<string, LucideIcon> = {
  euro: Banknote,
  banknote: Banknote,
  users: Heart,
  heart: Heart,
  zap: Zap,
  thermometer: Thermometer,
  "thermometer-snowflake": Thermometer,
  shield: Shield,
  "shield-check": Shield,
  sun: Sun,
  clock: Clock,
  droplets: Droplets,
  snowflake: Snowflake,
  brain: Brain,
  "thermometer-sun": Brain,
  eye: Eye,
};

/** Icônes des certifications (nom WP -> icône lucide de l'original). */
const CERT_ICONS: Record<string, LucideIcon> = {
  "Broof(t3)": Flame,
  "Avis technique CSTB": FileCheck2,
  RE2020: Building2,
  "Décret tertiaire": BadgeCheck,
  "Prime CEE BAT-EN-112": Droplets,
  "Formulation faible COV": Leaf,
  "Filtration UV certifiée": Sun,
  "Formulée en France": ShieldCheck,
};

// ---------------------------------------------------------------------------
// ProductHero — l'adaptateur reproduit l'appel exact de chaque vue d'origine
// ---------------------------------------------------------------------------

interface HeroDefaults {
  tag: string;
  productName: string;
  tagline: string;
  description: string;
  heroImage: string;
  heroImageAlt?: string;
  accentColor: string;
  primaryCTA: { label: string; href: string };
  secondaryCTA: { label: string; href: string };
  inlineBadges: string[];
  heroStats: { value: string; label: string }[];
}

const makeProductHero = (d: HeroDefaults) =>
  function ProductHeroAdapter(s: Section<HeroBlock>) {
    // Couleur d'accent : champ WP fiche_produit.accent_color s'il est renseigné,
    // sinon le défaut d'origine (parité). Propagée par BlockRenderer.
    const accent = useAccentColor();
    const img = mapImage(s.image);
    const badges = arr(s.badges)
      .map((b) => b.texte ?? "")
      .filter(Boolean);
    const stats = arr(s.stats)
      .filter((st) => st.value || st.label)
      .map((st) => ({ value: st.value ?? "", label: st.label ?? "" }));
    return (
      <ProductHero
        tag={s.eyebrow ?? d.tag}
        productName={s.titre ?? d.productName}
        tagline={d.tagline}
        description={s.lead ?? d.description}
        heroImage={img?.sourceUrl ?? d.heroImage}
        heroImageAlt={img?.altText || d.heroImageAlt}
        accentColor={accent || d.accentColor}
        primaryCTA={
          s.ctaPrimaire?.label
            ? { label: s.ctaPrimaire.label, href: s.ctaPrimaire.lien ?? d.primaryCTA.href }
            : d.primaryCTA
        }
        secondaryCTA={
          s.ctaSecondaire?.label
            ? { label: s.ctaSecondaire.label, href: s.ctaSecondaire.lien ?? d.secondaryCTA.href }
            : d.secondaryCTA
        }
        inlineBadges={badges.length ? badges : d.inlineBadges}
        heroStats={stats.length ? stats : d.heroStats}
      />
    );
  };

const ProductHeroCovaTherm = makeProductHero({
  tag: "Peinture cool roof professionnelle",
  productName: "CovaTherm",
  tagline: "La peinture cool roof la plus durable du marché.",
  description:
    "La peinture blanche réfléchissante haute performance signée Covalba, pionnier français du cool roof depuis 2018. Résine polyuréthane, SRI 118, garantie 20 ans, pour les toitures industrielles et tertiaires les plus exigeantes.",
  heroImage: covathermHero.src,
  accentColor: "#038d92",
  primaryCTA: { label: "Demander un devis", href: "/diagnostic" },
  secondaryCTA: { label: "Télécharger la fiche technique", href: "#fiche-technique" },
  inlineBadges: ["SRI 119", "20 ans de garantie", "Prime CEE éligible"],
  heroStats: [
    { value: "-10°C", label: "Température intérieure" },
    { value: "40%", label: "d'économie d'énergie" },
    { value: "20 ans", label: "de durabilité" },
  ],
});

const ProductHeroCovaThermLight = makeProductHero({
  tag: "Peinture anti-UV pour polycarbonate",
  productName: "CovaTherm Light",
  tagline: "La laque solaire qui bloque la chaleur sans voler la lumière.",
  description:
    "Revêtement acrylique blanc haute réflectivité, signé Covalba, pionnier français du cool roof depuis 2018. Appliquée sur vos lanterneaux, voûtes éclairantes et puits de lumière en polycarbonate ou polyester, elle filtre les UV, les infrarouges et l'éblouissement, tout en préservant jusqu'à 65 % de la luminosité naturelle.",
  heroImage: covathermLightHero.src,
  heroImageAlt: "Application de CovaTherm Light peinture anti-UV sur lanterneau polycarbonate",
  accentColor: "#0d3840",
  primaryCTA: { label: "Demander un devis", href: "/diagnostic" },
  secondaryCTA: { label: "Télécharger la fiche technique", href: "#specs" },
  inlineBadges: ["98 % des UV filtrés", "65 % de lumière préservée", "5 à 8 ans"],
  heroStats: [
    { value: "-5°C", label: "Sous les lanterneaux" },
    { value: "65 %", label: "de lumière préservée" },
    { value: "10 à 20 %", label: "de clim économisée" },
  ],
});

const ProductHeroCovaSeal = makeProductHero({
  tag: "Étanchéité cool roof professionnelle",
  productName: "CovaSeal 20",
  tagline: "L'étanchéité liquide cool roof 2-en-1.",
  description:
    "Résine acrylique élastomère avec Top Coat anti-UV, signée Covalba, pionnier français du cool roof depuis 2018. Une seule application pour restaurer l'étanchéité de votre toiture et gagner jusqu'à -10°C en intérieur, avec une garantie 20 ans.",
  heroImage: covasealHero.src,
  heroImageAlt: "Application de CovaSeal 20 étanchéité cool roof au rouleau sur toiture industrielle",
  accentColor: "#e18300",
  primaryCTA: { label: "Demander un devis", href: "/diagnostic" },
  secondaryCTA: { label: "Télécharger la fiche technique", href: "#specs" },
  inlineBadges: ["SRI 107", "20 ans de garantie", "Prime CEE éligible"],
  heroStats: [
    { value: "-8 à -10°C", label: "Température intérieure" },
    { value: "20 ans", label: "d'étanchéité + cool roof" },
    { value: "Prime CEE", label: "Éligible sous conditions" },
  ],
});

const ProductHeroCovaMetal = makeProductHero({
  tag: "Peinture cool roof bac acier professionnelle",
  productName: "CovaMetal 20",
  tagline: "La peinture cool roof 3-en-1 pour toitures métalliques corrodées.",
  description:
    "Résine élastomère avec Top Coat anti-UV, signée Covalba, pionnier français du cool roof depuis 2018. Une seule application pour traiter la corrosion, restaurer l'étanchéité et gagner jusqu'à -10°C en intérieur, avec une garantie 20 ans.",
  heroImage: covametalHero.src,
  heroImageAlt: "Application de CovaMetal 20 peinture cool roof sur toiture bac acier corrodé",
  accentColor: "#a9272e",
  primaryCTA: { label: "Demander un devis", href: "/diagnostic" },
  secondaryCTA: { label: "Télécharger la fiche technique", href: "#specs" },
  inlineBadges: ["SRI 107", "20 ans de garantie", "Prime CEE éligible"],
  heroStats: [
    { value: "-8 à -10°C", label: "Température intérieure" },
    { value: "20 ans", label: "d'anti-corrosion + cool roof" },
    { value: "Prime CEE", label: "Éligible sous conditions" },
  ],
});

// ---------------------------------------------------------------------------
// ProductShowcase (variantes_produit, CovaTherm)
// ---------------------------------------------------------------------------

const SHOWCASE_INTRO_COVATHERM =
  "Deux peintures cool roof polyuréthane qui partagent la même base technique brevetée. Seule la finition change, selon l'âge de votre toiture et votre horizon d'amortissement.";

function ProductShowcaseAdapter(s: Section<VariantesProduitBlock>) {
  const wp = arr(s.variantes);
  const variants = wp.length
    ? wp.map((v, i) => {
        const base = defaultVariants[i] ?? defaultVariants[defaultVariants.length - 1];
        return {
          ...base,
          name: v.nom ?? base.name,
          tagline: v.usage ?? base.tagline,
          description: v.description ?? base.description,
        };
      })
    : undefined;
  return (
    <ProductShowcase
      badge={s.entete?.badge ?? undefined}
      titre={accentNode(s.entete?.titre, "text-teal-vivid")}
      intro={richOr(s.entete?.intro, SHOWCASE_INTRO_COVATHERM)}
      variants={variants}
    />
  );
}

// ---------------------------------------------------------------------------
// CompatibilityTabs (compatibilite_supports) — un adaptateur par produit
// ---------------------------------------------------------------------------

interface CompatRoof {
  type: string;
  detail: string;
  incompatible?: boolean;
  image?: string;
}

interface CompatDefaults {
  productName: string;
  fallbackRoofs: CompatRoof[];
  introNode?: ReactNode;
  introText?: string;
  coverageNote?: string;
  footerNode?: ReactNode;
  footerText?: string;
  incompatibleTypes?: string[];
}

const makeCompatibilityTabs = (d: CompatDefaults) =>
  function CompatibilityTabsAdapter(s: Section<CompatibiliteSupportsBlock>) {
    const roofs: CompatRoof[] = arr(s.supports).map((r) => {
      const img = mapImage(r.image);
      return {
        type: r.type ?? "",
        detail: r.detail ?? "",
        image: img?.sourceUrl,
        incompatible: d.incompatibleTypes?.includes(r.type ?? "") || undefined,
      };
    });
    // note_couverture : 1re ligne = note de couverture, suite = note de pied.
    const lines = (s.noteCouverture ?? "")
      .split("\n")
      .map((l) => l.trim())
      .filter(Boolean);
    const wpFooter = lines.slice(1).join(" ");
    const wpIntro = s.entete?.intro;
    return (
      <CompatibilityTabs
        productName={d.productName}
        compatibleRoofs={roofs.length ? roofs : d.fallbackRoofs}
        badge={s.entete?.badge ?? undefined}
        titre={accentNode(s.entete?.titre, "text-foreground/45")}
        intro={
          wpIntro
            ? d.introText && norm(wpIntro) === d.introText
              ? d.introNode
              : <p>{wpIntro}</p>
            : d.introNode
        }
        coverageNote={lines[0] ?? d.coverageNote}
        footerNote={
          wpFooter
            ? d.footerText && norm(wpFooter) === d.footerText
              ? d.footerNode
              : wpFooter
            : d.footerNode
        }
      />
    );
  };

const CompatibilityTabsCovaTherm = makeCompatibilityTabs({
  productName: "CovaTherm",
  fallbackRoofs: [
    {
      type: "Membrane bitumineuse",
      detail: "Toiture plate ou légèrement en pente, en bon état général. 80% de nos chantiers.",
      image: compatBitume.src,
    },
    {
      type: "Béton / dalle béton",
      detail: "Surface solide, non fissurée. Adhérence parfaite sur béton brut ou peint.",
      image: compatBeton.src,
    },
    {
      type: "EPDM (caoutchouc)",
      detail: "Membrane EPDM en bon état. Préparation de surface par notre technicien.",
      image: compatEpdm.src,
    },
    {
      type: "Fibrociment",
      detail: "Surface poreuse compatible, sans fibres apparentes. Bilan technique obligatoire.",
      image: compatFibrociment.src,
    },
    {
      type: "Ardoise et tuile",
      detail: "Toits légèrement inclinés, jusqu'à 15° de pente.",
      image: compatArdoise.src,
    },
    {
      type: "PVC et membrane synthétique",
      detail: "Toiture PVC en bon état. Test d'adhérence préalable.",
      image: compatPvc.src,
    },
  ],
  introNode: (
    <p>
      Une peinture cool roof ne tient que si elle adhère durablement au support. Chaque chantier démarre par un <strong className="text-foreground">diagnostic préalable</strong> confié à un <strong className="text-foreground">applicateur certifié Covalba</strong>.
    </p>
  ),
  introText:
    "Une peinture cool roof ne tient que si elle adhère durablement au support. Chaque chantier démarre par un diagnostic préalable confié à un applicateur certifié Covalba.",
  coverageNote:
    "80% des toitures industrielles et tertiaires françaises sont en membrane bitumineuse.",
  footerNode: (
    <>
      Toiture en bac acier ? Voir notre{' '}
      <a href="/covametal" className="text-primary font-semibold hover:underline">
        peinture cool roof pour bac acier
      </a>{' '}
      dédiée, CovaMetal 20.
    </>
  ),
  footerText:
    "Toiture en bac acier ? Voir notre peinture cool roof pour bac acier dédiée, CovaMetal 20.",
});

const CompatibilityTabsCovaThermLight = makeCompatibilityTabs({
  productName: "CovaTherm Light",
  fallbackRoofs: [
    {
      type: "Polycarbonate",
      detail:
        "Matériau majoritaire sur les lanterneaux et voûtes éclairantes modernes, très sensible aux UV. Cœur de cible.",
      image: compatPolycarbonate.src,
    },
    {
      type: "Polyester translucide",
      detail: "Utilisé sur les voûtes éclairantes et certains skydômes anciens.",
      image: compatPolyester.src,
    },
    {
      type: "Fibre de verre translucide",
      detail: "Compatibilité validée après diagnostic technique sur site.",
      image: compatFibreVerre.src,
    },
    {
      type: "Vitrage",
      detail:
        "Verre, verrière, véranda : un film solaire intérieur collé est la solution adaptée, pas la laque solaire.",
      incompatible: true,
      image: compatVitrage.src,
    },
  ],
  introNode: (
    <p>
      Une laque solaire ne tient sa promesse que si elle adhère durablement au
      support translucide sans opacifier sa lumière. Chaque chantier démarre par
      un <strong className="text-foreground">diagnostic préalable</strong> confié
      à un <strong className="text-foreground">applicateur certifié Covalba</strong>.
    </p>
  ),
  introText:
    "Une laque solaire ne tient sa promesse que si elle adhère durablement au support translucide sans opacifier sa lumière. Chaque chantier démarre par un diagnostic préalable confié à un applicateur certifié Covalba.",
  coverageNote:
    "CovaTherm Light est formulée pour les matériaux translucides utilisés en couverture de bâtiment.",
  footerNode: (
    <>
      Pour la partie opaque de votre toiture, voir notre{' '}
      <a href="/peinture-reflective-covatherm" className="text-primary font-semibold hover:underline">
        peinture cool roof CovaTherm
      </a>
      .
    </>
  ),
  footerText: "Pour la partie opaque de votre toiture, voir notre peinture cool roof CovaTherm.",
  incompatibleTypes: ["Vitrage"],
});

const CompatibilityTabsCovaSeal = makeCompatibilityTabs({
  productName: "CovaSeal 20",
  fallbackRoofs: [
    {
      type: "Étanchéité bitumineuse",
      detail: "Membrane bitumineuse vieillissante, posée depuis plus d'un an.",
      image: compatBitume.src,
    },
    {
      type: "Membrane EPDM",
      detail: "Membrane caoutchouc EPDM de plus de 10 ans, avec test d'adhérence préalable.",
      image: compatEpdm.src,
    },
    {
      type: "Membrane PVC",
      detail:
        "Membrane synthétique PVC de plus de 10 ans. Préparation de surface par notre technicien.",
      image: compatPvc.src,
    },
    {
      type: "Tuiles",
      detail: "Tuiles terre cuite ou béton, légèrement inclinées, en bon état structurel.",
      image: compatTuile.src,
    },
    {
      type: "Ardoises",
      detail: "Toitures ardoise avec pente modérée, sans casses majeures.",
      image: compatArdoise.src,
    },
    {
      type: "Fibrociment",
      detail: "Surface poreuse compatible, sans fibres apparentes. Bilan technique obligatoire.",
      image: compatFibrociment.src,
    },
  ],
  coverageNote:
    "Un enduit d'étanchéité cool roof ne tient sa promesse que s'il adhère durablement au support.",
});

const CompatibilityTabsCovaMetal = makeCompatibilityTabs({
  productName: "CovaMetal 20",
  fallbackRoofs: [
    {
      type: "Bac acier",
      detail: "Plaques galvanisées, peintes ou brutes, avec ou sans corrosion. Cœur de cible.",
      image: compatBacAcier.src,
    },
    {
      type: "Tôle ondulée métallique",
      detail: "Tôles ondulées ou nervurées, avec ou sans corrosion de surface.",
      image: compatToleOndulee.src,
    },
    {
      type: "Zinc",
      detail: "Toitures en zinc vieillissantes, adhérence vérifiée par test préalable.",
      image: compatZinc.src,
    },
    {
      type: "Autres supports métalliques",
      detail: "Compatibilité validée après diagnostic technique sur site.",
      image: compatMetalGenerique.src,
    },
  ],
  coverageNote:
    "Un revêtement cool roof anti-corrosion ne tient sa promesse que s'il adhère durablement au support métallique.",
});

// ---------------------------------------------------------------------------
// Specs techniques (specs_techniques)
// ---------------------------------------------------------------------------

const SPECS_INTRO_COVATHERM =
  "Performances thermiques identiques à l'application. La différence se joue dans la durée : CovaTherm 8 tient 8 à 10 ans, CovaTherm 20 pousse à 20 ans grâce à sa finition Top Coat anti-UV. Loin des peintures cool roof acryliques du marché, qui tiennent 2 à 5 ans.";

function TechnicalSpecsAdapter(s: Section<SpecsTechniquesBlock>) {
  const cols = arr(s.colonnesSpecs);
  const lignes = arr(s.lignesSpecs);
  const specs = lignes.length
    ? lignes.map((r) => ({
        label: r.label ?? "",
        v8: cellValue(r.valeurs?.[0]?.texte),
        v20: cellValue(r.valeurs?.[1]?.texte),
      }))
    : undefined;
  return (
    <TechnicalSpecs
      badge={s.entete?.badge ?? undefined}
      titre={accentNode(s.entete?.titre, "text-foreground/45")}
      intro={richOr(s.entete?.intro, SPECS_INTRO_COVATHERM)}
      specs={specs}
      nomCol8={cols[0]?.nom ?? undefined}
      nomCol20={cols[1]?.nom ?? undefined}
    />
  );
}

const makeSpecs = (
  Comp: ComponentType<{
    badge?: string;
    titre?: ReactNode;
    intro?: ReactNode;
    specs?: { label: string; value: string | boolean | null }[];
    nomColonne?: string;
  }>,
) =>
  function SpecsAdapter(s: Section<SpecsTechniquesBlock>) {
    const cols = arr(s.colonnesSpecs);
    const lignes = arr(s.lignesSpecs);
    const specs = lignes.length
      ? lignes.map((r) => ({
          label: r.label ?? "",
          value: cellValue(r.valeurs?.[0]?.texte),
        }))
      : undefined;
    return (
      <Comp
        badge={s.entete?.badge ?? undefined}
        titre={accentNode(s.entete?.titre, "text-foreground/45")}
        intro={s.entete?.intro ?? undefined}
        specs={specs}
        nomColonne={cols[0]?.nom ?? undefined}
      />
    );
  };

const CovaSealSpecsAdapter = makeSpecs(CovaSealSpecs);
const CovaMetalSpecsAdapter = makeSpecs(CovaMetalSpecs);
const CovaThermLightSpecsAdapter = makeSpecs(CovaThermLightSpecs);

// ---------------------------------------------------------------------------
// Avantages (grille_cards)
// ---------------------------------------------------------------------------

const makeAdvantages = (
  Comp: ComponentType<{
    badge?: string;
    titre?: ReactNode;
    intro?: ReactNode;
    advantages?: { icon: LucideIcon; title: string; desc: string }[];
  }>,
  introDefault: string,
  iconOverrides: Record<string, LucideIcon> = {},
) =>
  function AdvantagesAdapter(s: Section<GrilleCardsBlock>) {
    const cards = arr(s.cards);
    const advantages = cards.length
      ? cards.map((c) => ({
          icon: iconOverrides[c.icone ?? ""] ?? CARD_ICONS[c.icone ?? ""] ?? BadgeCheck,
          title: c.titre ?? "",
          desc: c.texte ?? "",
        }))
      : undefined;
    return (
      <Comp
        badge={s.entete?.badge ?? undefined}
        titre={accentNode(s.entete?.titre, "text-teal-vivid", { br: false })}
        intro={richOr(s.entete?.intro, introDefault)}
        advantages={advantages}
      />
    );
  };

const ProductAdvantagesAdapter = makeAdvantages(
  ProductAdvantages,
  "Appliquer une peinture cool roof sur une toiture professionnelle produit des effets mesurables dès le premier été. Six bénéfices constatés sur nos chantiers, chiffres à l'appui.",
);
const CovaSealAdvantagesAdapter = makeAdvantages(
  CovaSealAdvantages,
  "Appliquer CovaSeal 20 sur une toiture fatiguée produit un double effet dès le premier été : l'étanchéité est restaurée et la température intérieure baisse de façon mesurable. Voici les six bénéfices constatés sur nos chantiers, chiffres à l'appui.",
);
const CovaMetalAdvantagesAdapter = makeAdvantages(
  CovaMetalAdvantages,
  "Appliquer CovaMetal 20 sur une toiture métallique corrodée produit un triple effet dès la première saison : la corrosion est stoppée, l'étanchéité est restaurée, et la température intérieure baisse de façon mesurable. Voici les six bénéfices constatés sur nos chantiers.",
);
const CovaThermLightAdvantagesAdapter = makeAdvantages(
  CovaThermLightAdvantages,
  "Appliquer CovaTherm Light sur vos lanterneaux transforme l'ambiance intérieure de votre bâtiment dès le premier été : la chaleur radiante disparaît, l'éblouissement cesse, mais la lumière naturelle reste. Voici les six bénéfices constatés sur nos chantiers.",
  // Mapping spécifique CovaTherm Light (icônes d'origine : Brain et Eye)
  { "thermometer-sun": Brain, "shield-check": Eye },
);

// ---------------------------------------------------------------------------
// Certifications (certifications)
// ---------------------------------------------------------------------------

const makeCertifications = (
  Comp: ComponentType<{
    badge?: string;
    titre?: ReactNode;
    intro?: ReactNode;
    certifications?: { icon: LucideIcon; label: string; desc: string }[];
  }>,
) =>
  function CertificationsAdapter(s: Section<CertificationsBlock>) {
    const items = arr(s.itemsCertifications);
    const certifications = items.length
      ? items.map((c) => ({
          icon: CERT_ICONS[c.nom ?? ""] ?? BadgeCheck,
          label: c.nom ?? "",
          desc: c.description ?? "",
        }))
      : undefined;
    return (
      <Comp
        badge={s.entete?.badge ?? undefined}
        titre={accentNode(s.entete?.titre, "text-foreground/45")}
        intro={s.entete?.intro ?? undefined}
        certifications={certifications}
      />
    );
  };

const CovaSealCertificationsAdapter = makeCertifications(CovaSealCertifications);
const CovaMetalCertificationsAdapter = makeCertifications(CovaMetalCertifications);
const CovaThermLightCertificationsAdapter = makeCertifications(CovaThermLightCertifications);

// ---------------------------------------------------------------------------
// Comparatifs (tableau_comparatif)
// ---------------------------------------------------------------------------

const makeComparison = (
  Comp: ComponentType<{
    badge?: string;
    titre?: ReactNode;
    intro?: ReactNode;
    rows?: { label: string; a: string; b: string; c?: string }[];
    colA?: string;
    colB?: string;
    colC?: string;
    texteApres?: ReactNode;
  }>,
  texteApresDefault: string,
  withC: boolean,
) =>
  function ComparisonAdapter(s: Section<TableauComparatifBlock>) {
    const cols = arr(s.entetesColonnes).map((c) => c.texte ?? "");
    const lignes = arr(s.lignesComparatif);
    const rows = lignes.length
      ? lignes.map((l) => {
          const cells = arr(l.cellules).map((x) => x.texte ?? "");
          return withC
            ? { label: cells[0] ?? "", a: cells[1] ?? "", b: cells[2] ?? "", c: cells[3] ?? "" }
            : { label: cells[0] ?? "", a: cells[1] ?? "", b: cells[2] ?? "" };
        })
      : undefined;
    return (
      <Comp
        badge={s.entete?.badge ?? undefined}
        titre={accentNode(s.entete?.titre, "text-foreground/45")}
        intro={s.entete?.intro ?? undefined}
        rows={rows}
        colA={cols[0] || undefined}
        colB={cols[1] || undefined}
        colC={withC ? cols[2] || undefined : undefined}
        texteApres={richOr(s.texteApres, texteApresDefault)}
      />
    );
  };

const CovaSealComparisonAdapter = makeComparison(
  CovaSealComparison,
  "CovaSeal 20 est la solution qui s'amortit le plus rapidement, sans démontage ni interruption d'activité. Elle s'impose comme la référence pour les bâtiments industriels, pharmaceutiques, agroalimentaires, aéronautiques et tertiaires dont la toiture est fatiguée mais encore exploitable. Pour une toiture métallique type bac acier, la peinture cool roof pour bac acier CovaMetal 20 est mieux adaptée.",
  true,
);
const CovaMetalComparisonAdapter = makeComparison(
  CovaMetalComparison,
  "CovaMetal 20 est la solution qui s'amortit le plus rapidement, sans démontage ni interruption d'activité. Elle s'impose comme la référence pour les bâtiments industriels, logistiques et agricoles dont la toiture bac acier est corrodée en surface mais encore structurellement exploitable. Pour une toiture non métallique (bitume, béton, membrane), la peinture étanchéité cool roof CovaSeal 20 est mieux adaptée.",
  false,
);
const CovaThermLightComparisonAdapter = makeComparison(
  CovaThermLightComparison,
  "CovaTherm Light est la solution adaptée quand les lanterneaux sont encore structurellement sains mais provoquent un inconfort thermique et lumineux. Pour des voûtes éclairantes très jaunies, déformées ou en fin de vie, un remplacement ponctuel des éléments concernés est préférable avant d'envisager une laque solaire sur le reste. Pour la partie opaque de votre toiture, la peinture cool roof CovaTherm complète le traitement.",
  false,
);

// ---------------------------------------------------------------------------
// FAQ (faq)
// ---------------------------------------------------------------------------

const makeFaq = (productName: string, fallback: ProductFaqEntry[]) =>
  function FaqAdapter(s: Section<FaqBlock>) {
    const questions = arr(s.questions);
    const faqs = questions.length
      ? questions.map((q) => ({
          q: q.question ?? "",
          a: (
            <div
              className="[&_a]:text-primary [&_a]:font-semibold [&_a:hover]:underline"
              dangerouslySetInnerHTML={{ __html: sanitizeWpHtml(q.reponse) }}
            />
          ),
        }))
      : fallback.map(({ q, text }) => ({ q, a: text as ReactNode }));
    return (
      <ProductFAQ
        productName={productName}
        faqs={faqs}
        badge={s.entete?.badge ?? undefined}
        titre={s.entete?.titre ?? undefined}
        intro={s.entete?.intro ?? undefined}
        ctaLabel={s.cta?.label ?? undefined}
        ctaHref={s.cta?.lien ?? undefined}
      />
    );
  };

const ProductFAQCovaTherm = makeFaq("CovaTherm", covathermFaqs);
const ProductFAQCovaThermLight = makeFaq("CovaTherm Light", covathermLightFaqs);
const ProductFAQCovaSeal = makeFaq("CovaSeal 20", covasealFaqs);
const ProductFAQCovaMetal = makeFaq("CovaMetal 20", covametalFaqs);

// ---------------------------------------------------------------------------
// Contenu SEO (contenu_seo) — guide CovaTherm + dossiers éditoriaux
//
// Si le contenu WP est identique au seed (hash du texte normalisé), on rend
// le composant original sans props : le corps riche d'origine (puces custom,
// liens stylés…) garantit la parité pixel. Dès qu'un texte est édité dans le
// BO, on bascule sur le rendu HTML générique.
// ---------------------------------------------------------------------------

const makeContenuSeo = (
  Comp: ComponentType<{
    intro?: string;
    sections?: { titre?: string | null; contenu?: string | null }[];
    sources?: { ref: string; url: string }[];
  }>,
  seedDigest: number,
  opts: { stripIntroP?: boolean } = {},
) =>
  function ContenuSeoAdapter(s: Section<ContenuSeoBlock>) {
    const sections = arr(s.sections);
    const digest =
      norm(s.intro ?? "") +
      sections.map((x) => norm(x.titre ?? "") + norm(x.contenu ?? "")).join("");
    if (hash(digest) === seedDigest) return <Comp />;
    const sources = arr(s.sources)
      .filter((x) => x.label)
      .map((x) => ({ ref: x.label ?? "", url: x.url ?? "" }));
    return (
      <Comp
        intro={s.intro ? (opts.stripIntroP ? stripOuterP(s.intro) : s.intro) : undefined}
        sections={sections.length ? sections : undefined}
        sources={sources.length ? sources : undefined}
      />
    );
  };

const CoolRoofGuideAdapter = makeContenuSeo(CoolRoofGuide, 564420437, { stripIntroP: true });
const CovaSealEditorialAdapter = makeContenuSeo(CovaSealEditorial, 1375046801);
const CovaMetalEditorialAdapter = makeContenuSeo(CovaMetalEditorial, 2432885520);
const CovaThermLightEditorialAdapter = makeContenuSeo(CovaThermLightEditorial, 2142459583);

// ---------------------------------------------------------------------------
// Autres solutions (grille_solutions)
// ---------------------------------------------------------------------------

const makeRelated = (currentProduct: string) =>
  function RelatedProductsAdapter(s: Section<GrilleSolutionsBlock>) {
    const slugs = arr(s.produits?.nodes)
      .map((n) => n.slug)
      .filter((x): x is string => !!x);
    const products = slugs
      .map((slug) => allProducts.find((p) => p.href.endsWith(`/${slug}`)))
      .filter((p): p is RelatedProductItem => !!p);
    return (
      <RelatedProducts
        currentProduct={currentProduct}
        badge={s.entete?.badge ?? undefined}
        titre={s.entete?.titre ?? undefined}
        products={products.length ? products : undefined}
      />
    );
  };

const RelatedProductsCovaTherm = makeRelated("CovaTherm");
const RelatedProductsCovaThermLight = makeRelated("CovaTherm Light");
const RelatedProductsCovaSeal = makeRelated("CovaSeal 20");
const RelatedProductsCovaMetal = makeRelated("CovaMetal 20");

// ---------------------------------------------------------------------------
// Showcases dédiés (texte_image "Positionnement")
// ---------------------------------------------------------------------------

const makeShowcase = (
  Comp: ComponentType<{
    badge?: string;
    titre?: ReactNode;
    contenu?: string;
    image?: string;
    imageAlt?: string;
    ctaLabel?: string;
    ctaHref?: string;
    note?: ReactNode;
  }>,
  contenuDefault: string,
) =>
  function ShowcaseAdapter(s: Section<TexteImageBlock>) {
    const img = mapImage(s.image);
    return (
      <Comp
        badge={s.entete?.badge ?? undefined}
        titre={accentNode(s.entete?.titre, "text-teal-vivid")}
        contenu={richOr(s.contenu, contenuDefault)}
        image={img?.sourceUrl}
        imageAlt={img?.altText || undefined}
        ctaLabel={s.cta?.label ?? undefined}
        ctaHref={s.cta?.lien ?? undefined}
        note={s.note ?? undefined}
      />
    );
  };

const CovaSealShowcaseAdapter = makeShowcase(
  CovaSealShowcase,
  "Système 2 couches qui combine la performance thermique d'une peinture cool roof et la protection d'une étanchéité polyuréthane acrylique élastomère sur le même chantier. Pensé pour les toitures qui présentent des microfissures, des boursouflures ou de petites infiltrations. Rebouche jusqu'à 2 mm , protège et rafraîchit sans réfection complète. Base Coat — étanchéité liquide cool roof (2 à 3 kg/m²). Top Coat — finition anti-encrassement haute durabilité.",
);
const CovaMetalShowcaseAdapter = makeShowcase(
  CovaMetalShowcase,
  "Une seule application pour traiter simultanément les trois problèmes récurrents des toitures en bac acier vieillissantes : corrosion, fuites sur chevauchements et surchauffe estivale. Anti-corrosion — stoppe la progression de la rouille sur le métal exposé. Étanchéité — membrane élastique à 200 % d'allongement sur chevauchements et points de fixation. Cool roof — jusqu'à 90 % de rayonnement solaire réfléchi, sur 20 ans.",
);
const CovaThermLightShowcaseAdapter = makeShowcase(
  CovaThermLightShowcase,
  "Le seul revêtement cool roof conçu pour les surfaces qu'on ne peut pas peindre en blanc opaque sans sacrifier la lumière naturelle. Filtre sélectivement UV et infrarouges, laisse passer le spectre visible. Polycarbonate — lanterneaux, voûtes éclairantes, skydômes modernes. Polyester translucide — voûtes éclairantes et skydômes anciens.",
);

// ---------------------------------------------------------------------------
// Avant / après (avant_apres, CovaTherm Light)
// ---------------------------------------------------------------------------

function CovaThermLightBeforeAfterAdapter(s: Section<AvantApresBlock>) {
  const avant = mapImage(s.imageAvant);
  const apres = mapImage(s.imageApres);
  return (
    <CovaThermLightBeforeAfter
      badge={s.entete?.badge ?? undefined}
      titre={accentNode(s.entete?.titre, "text-foreground/45")}
      intro={s.entete?.intro ?? undefined}
      imageAvant={avant?.sourceUrl}
      imageApres={apres?.sourceUrl}
      altAvant={avant?.altText || undefined}
      altApres={apres?.altText || undefined}
      legendeAvant={s.legendeAvant ? s.legendeAvant.replace(/^avant\.?\s*/i, "") : undefined}
      legendeApres={s.legendeApres ? s.legendeApres.replace(/^après\.?\s*/i, "") : undefined}
    />
  );
}

// ---------------------------------------------------------------------------
// Registry
// ---------------------------------------------------------------------------

// Adaptateurs hétérogènes selon les sections WordPress d'origine.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const origineProduits: Record<string, ComponentType<any>> = {
  // Héros (un par produit : tagline/accentColor proviennent de la vue d'origine)
  ProductHeroCovaTherm,
  ProductHeroCovaThermLight,
  ProductHeroCovaSeal,
  ProductHeroCovaMetal,

  // Sections génériques configurées par vue
  ProductShowcase: ProductShowcaseAdapter,
  CompatibilityTabsCovaTherm,
  CompatibilityTabsCovaThermLight,
  CompatibilityTabsCovaSeal,
  CompatibilityTabsCovaMetal,
  TechnicalSpecs: TechnicalSpecsAdapter,
  ProductAdvantages: ProductAdvantagesAdapter,
  ProductFAQCovaTherm,
  ProductFAQCovaThermLight,
  ProductFAQCovaSeal,
  ProductFAQCovaMetal,
  CoolRoofGuide: CoolRoofGuideAdapter,
  RelatedProductsCovaTherm,
  RelatedProductsCovaThermLight,
  RelatedProductsCovaSeal,
  RelatedProductsCovaMetal,

  // CovaSeal 20
  CovaSealShowcase: CovaSealShowcaseAdapter,
  CovaSealSpecs: CovaSealSpecsAdapter,
  CovaSealCertifications: CovaSealCertificationsAdapter,
  CovaSealAdvantages: CovaSealAdvantagesAdapter,
  CovaSealComparison: CovaSealComparisonAdapter,
  CovaSealEditorial: CovaSealEditorialAdapter,

  // CovaMetal 20
  CovaMetalShowcase: CovaMetalShowcaseAdapter,
  CovaMetalSpecs: CovaMetalSpecsAdapter,
  CovaMetalCertifications: CovaMetalCertificationsAdapter,
  CovaMetalAdvantages: CovaMetalAdvantagesAdapter,
  CovaMetalComparison: CovaMetalComparisonAdapter,
  CovaMetalEditorial: CovaMetalEditorialAdapter,

  // CovaTherm Light
  CovaThermLightShowcase: CovaThermLightShowcaseAdapter,
  CovaThermLightBeforeAfter: CovaThermLightBeforeAfterAdapter,
  CovaThermLightSpecs: CovaThermLightSpecsAdapter,
  CovaThermLightCertifications: CovaThermLightCertificationsAdapter,
  CovaThermLightAdvantages: CovaThermLightAdvantagesAdapter,
  CovaThermLightComparison: CovaThermLightComparisonAdapter,
  CovaThermLightEditorial: CovaThermLightEditorialAdapter,
};
