import type { ZoneData } from '@/data/zones';
import type { SEOTemplate } from '@/content/seo/template';
import { buildSeoContent } from '@/content/seo/generate';
import { departementInPhrase, zoneInPhrase, zoneName } from '@/lib/zoneGeo';
import { sanitizeWpHtml } from '@/lib/sanitizeHtml';
import ScrollReveal from './ScrollReveal';

interface SEOContentSectionProps {
  zoneData: ZoneData;
}

function resolveContent(zoneData: ZoneData): SEOTemplate {
  // Texte rédigé à la main prioritaire ; sinon dossier généré depuis les données réelles de la zone.
  if (zoneData.seoContent) return zoneData.seoContent;
  return buildSeoContent(zoneData);
}

/**
 * Découpe un texte en paragraphes sur les lignes vides (\n\n).
 * Rétro-compatible : un texte sans ligne vide reste un unique paragraphe.
 */
const toParagraphs = (text: string): string[] =>
  text
    .split(/\n\s*\n/)
    .map((p) => p.trim())
    .filter(Boolean);

type InternalTarget = {
  label: string;
  href: string;
};

const escapeHtml = (value: string): string =>
  value.replace(/[&<>"']/g, (char) => {
    switch (char) {
      case '&':
        return '&amp;';
      case '<':
        return '&lt;';
      case '>':
        return '&gt;';
      case '"':
        return '&quot;';
      case "'":
        return '&#039;';
      default:
        return char;
    }
  });

const escapeRegExp = (value: string): string => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

const currentSlug = (zoneData: ZoneData): string | undefined =>
  zoneData.slugVille ?? zoneData.slugDepartement ?? zoneData.slugRegion;

function internalTargets(zoneData: ZoneData): InternalTarget[] {
  const current = currentSlug(zoneData);
  const targets: InternalTarget[] = [];

  const add = (label?: string, slug?: string) => {
    if (!label || !slug || slug === current) return;
    if (targets.some((target) => target.href === `/${slug}` || target.label === label)) return;
    targets.push({ label, href: `/${slug}` });
  };

  if (zoneData.pageType === 'ville') {
    add(zoneData.departementNom, zoneData.slugDepartement);
  }
  if (zoneData.pageType !== 'region') {
    add(zoneData.region, zoneData.slugRegion);
  }

  (zoneData.maillage ?? []).forEach((item) => add(item.nom, item.slug));

  return targets;
}

function formatTargetLinks(targets: InternalTarget[]): string {
  const links = targets.map(
    (target) =>
      `<a href="${target.href}" class="seo-rich-link">${escapeHtml(target.label)}</a>`,
  );
  if (links.length <= 1) return links[0] ?? '';
  return `${links.slice(0, -1).join(', ')} et ${links[links.length - 1]}`;
}

function linkInlineTargets(html: string, zoneData: ZoneData, usedTargets: Set<string>): string {
  let output = html;
  let count = 0;

  for (const target of internalTargets(zoneData)) {
    if (count >= 2) break;
    if (usedTargets.size >= 6 || usedTargets.has(target.href)) continue;
    const label = escapeHtml(target.label);
    if (label.length < 3 || !output.includes(label)) continue;
    output = output.replace(label, `<a href="${target.href}" class="seo-rich-link">${label}</a>`);
    usedTargets.add(target.href);
    count += 1;
  }

  return output;
}

function replaceFirst(html: string, term: string, tag: 'strong' | 'em'): string {
  if (!term) return html;
  const pattern = new RegExp(escapeRegExp(escapeHtml(term)), 'i');
  return html.replace(pattern, (match) => `<${tag}>${match}</${tag}>`);
}

function emphasizeSeoHtml(html: string, zoneData: ZoneData): string {
  const strongTerms = [
    zoneName(zoneData),
    'CovaTherm',
    '90 % du rayonnement solaire',
    'SRI',
    'Prime CEE',
    'Décret tertiaire',
    '15 à 40 %',
    `8 à ${Math.round(zoneData.reductionSousToiture)} °C`,
  ];

  const emTerms = [
    'sans arrêt d’exploitation',
    "sans arrêt d'exploitation",
    'dès le premier été',
    'sous 48 heures',
    'sans climatisation supplémentaire',
    'fourchette haute des modèles',
  ];

  let output = html;
  strongTerms.forEach((term) => {
    output = replaceFirst(output, term, 'strong');
  });
  emTerms.forEach((term) => {
    output = replaceFirst(output, term, 'em');
  });

  return output;
}

function renderRichHtml(text: string, zoneData: ZoneData, usedTargets: Set<string>): string {
  const escaped = escapeHtml(text);
  return emphasizeSeoHtml(linkInlineTargets(escaped, zoneData, usedTargets), zoneData);
}

function buildTerritoryInsightHtml(zoneData: ZoneData, usedTargets: Set<string>): string {
  const name = escapeHtml(zoneName(zoneData));
  const phrase = escapeHtml(zoneInPhrase(zoneData));
  const sector = escapeHtml((zoneData.typeZone || "bâtiments d'activité").toLowerCase());
  const targets = internalTargets(zoneData).filter((target) => !usedTargets.has(target.href)).slice(0, 4);
  targets.forEach((target) => usedTargets.add(target.href));
  const links = formatTargetLinks(targets);
  const heat =
    zoneData.joursSup30C > 0
      ? `, avec <strong>${Math.round(zoneData.joursSup30C)} jours au-dessus de 30 °C</strong> aujourd’hui et ${Math.round(zoneData.joursSup30C20ans)} projetés à vingt ans`
      : '';

  if (zoneData.pageType === 'departement') {
    const deptPhrase = escapeHtml(departementInPhrase(zoneData.departementNom));
    return `${deptPhrase.charAt(0).toUpperCase()}${deptPhrase.slice(1)}, Covalba ne traite pas les sites comme un bloc uniforme : les toitures <strong>${sector}</strong> sont priorisées selon leur surface, leur exposition et leur dépendance à la climatisation${heat}. <em>La bonne entrée consiste à hiérarchiser les bâtiments avant de lancer les lots de travaux</em>${links ? `, notamment en comparant les secteurs ${links}` : ''}.`;
  }

  if (zoneData.pageType === 'region') {
    return `En <strong>${name}</strong>, le besoin cool roof varie fortement entre bassins logistiques, industriels et tertiaires${heat}. <em>Le diagnostic doit rester territorial</em> : même produit, mais priorités différentes selon l’exposition, la toiture et l’usage${links ? `, avec des analyses à rapprocher de ${links}` : ''}.`;
  }

  return `${name} se lit d’abord par ses usages réels : <strong>${sector}</strong>, toitures bac acier, terrasses techniques et contraintes d’exploitation${heat}. Pour un projet ${phrase}, <em>l’enjeu n’est pas seulement de blanchir une toiture, mais de traiter la bonne surface au bon moment</em>${links ? ` ; comparez aussi les pages ${links}` : ''}.`;
}

function buildInternalMeshHtml(zoneData: ZoneData, usedTargets: Set<string>): string {
  const targets = internalTargets(zoneData).filter((target) => !usedTargets.has(target.href));
  targets.forEach((target) => usedTargets.add(target.href));
  const links = formatTargetLinks(targets);
  if (!links) return '';

  if (zoneData.pageType === 'region') {
    return `Pour élargir le diagnostic, le dossier régional renvoie aussi vers ${links}. Ces pages permettent de comparer les priorités par département, type de toiture et bassin économique avant de planifier un déploiement cool roof.`;
  }

  if (zoneData.pageType === 'departement') {
    return `Pour affiner le plan d’intervention, le dossier départemental renvoie aussi vers ${links}. Ce maillage aide à comparer les villes, plateformes et zones d’activité où les toitures exposées doivent être traitées en priorité.`;
  }

  return `Pour comparer ce projet avec les secteurs voisins, consultez aussi ${links}. Ce maillage interne permet de rapprocher les contraintes de toiture, les zones d’activité et les priorités de déploiement cool roof autour du site étudié.`;
}

const SEOContentSection = ({ zoneData }: SEOContentSectionProps) => {
  const content = resolveContent(zoneData);

  // Prime CEE et Décret tertiaire sont des dispositifs franco-français :
  // on masque ces sections pour les zones hors France (Suisse, Belgique…).
  const isFrance = (zoneData.pays ?? 'FR') === 'FR';
  const sections = isFrance
    ? content.sections
    : content.sections.filter(
        (s) =>
          !/\b(cee|prime|décret tertiaire|decret tertiaire|certificat d)/i.test(`${s.h3} ${s.content}`),
      );
  const usedTargets = new Set<string>();
  const territoryInsight = buildTerritoryInsightHtml(zoneData, usedTargets);
  const internalMesh = buildInternalMeshHtml(zoneData, usedTargets);

  return (
    <section className="bg-cream py-20 lg:py-28">
      <div className="container mx-auto px-4 lg:px-8">
        <div className="max-w-4xl mx-auto">
          <ScrollReveal>
            <p className="text-[10px] uppercase tracking-[0.25em] font-semibold text-primary/50 font-body mb-6">
              Dossier
            </p>

            <h2
              className="font-satoshi text-3xl sm:text-4xl lg:text-[3rem] font-black text-foreground !leading-[1.05]"
              style={{ letterSpacing: '-0.03em' }}
            >
              {content.h2}
            </h2>

            <div className="mt-6 space-y-4">
              {toParagraphs(content.intro).map((p, i) => (
                <p
                  key={i}
                  className="seo-rich-text text-base lg:text-lg text-foreground/75 leading-relaxed font-body"
                  dangerouslySetInnerHTML={{ __html: sanitizeWpHtml(renderRichHtml(p, zoneData, usedTargets)) }}
                />
              ))}
              <p
                className="seo-rich-text text-base lg:text-lg text-foreground/75 leading-relaxed font-body"
                dangerouslySetInnerHTML={{ __html: sanitizeWpHtml(territoryInsight) }}
              />
              {internalMesh && (
                <p
                  className="seo-rich-text text-base lg:text-lg text-foreground/75 leading-relaxed font-body"
                  dangerouslySetInnerHTML={{ __html: sanitizeWpHtml(internalMesh) }}
                />
              )}
            </div>
          </ScrollReveal>

          <div className="space-y-14 text-foreground/75 leading-relaxed font-body mt-14">
            {sections.map((section, i) => (
              <ScrollReveal key={i}>
                <div>
                  <h3 className="font-satoshi text-2xl lg:text-3xl font-bold text-foreground mb-4">
                    {section.h3}
                  </h3>
                  <div className="space-y-4">
                    {toParagraphs(section.content).map((p, j) => (
                      <p
                        key={j}
                        className="seo-rich-text text-foreground/75 leading-relaxed font-body"
                        dangerouslySetInnerHTML={{ __html: sanitizeWpHtml(renderRichHtml(p, zoneData, usedTargets)) }}
                      />
                    ))}
                  </div>
                </div>
              </ScrollReveal>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
};

export default SEOContentSection;
