/* global React */
const { useEffect: useE_d } = React;

// local helpers for body block construction (mirror of cp-articles.js)
const _h2 = (text) => ({ kind: 'h2', text });
const _p = (text) => ({ kind: 'p', text });

function buildArticleBody(article, lang) {
  // Prefer per-article body if provided by cp-articles.js
  if (article && Array.isArray(article.body) && article.body.length) {
    return article.body;
  }
  const FR = [
    { kind: 'lede', text: article.dek },
    { kind: 'h2', text: 'Le contexte en bref' },
    { kind: 'p', text: 'Cet article reprend les éléments officiels publiés par IRCC et les sources provinciales reconnues. L’objectif n’est pas de prédire l’avenir, mais d’aider à lire les règles telles qu’elles existent en mai 2026, en évitant les raccourcis souvent vus dans les forums.' },
    { kind: 'p', text: 'Les programmes d’immigration changent régulièrement. Chaque section ci-dessous indique la date de dernière vérification, et les points où une situation personnelle peut faire varier l’interprétation.' },
    { kind: 'h2', text: 'Ce que disent les textes' },
    { kind: 'p', text: 'Les directives officielles posent un cadre relativement stable. La plupart des refus n’ont pas pour cause un changement de politique, mais une lecture imprécise du dossier au moment du dépôt. La rédaction recommande de relire trois fois la liste des pièces, à au moins une semaine d’intervalle.' },
    { kind: 'quote', text: 'Un dossier soigné ne garantit pas une réponse positive, mais il évite presque toujours les refus pour motifs administratifs.' },
    { kind: 'h2', text: 'Étapes pratiques' },
    { kind: 'p', text: 'Avant le dépôt, listez d’abord les documents officiels (passeport, actes d’état civil, diplômes). Ajoutez ensuite les éléments produits récemment (relevés de comptes, attestations d’emploi datées de moins de six mois, certifications linguistiques). Vérifiez enfin que chaque pièce correspond exactement à la liste fournie par le programme visé.' },
    { kind: 'h2', text: 'Pour aller plus loin' },
    { kind: 'list', items: [
      'Vérifier la liste des pièces sur le site officiel d’IRCC, en se méfiant des copies sur d’autres portails.',
      'Conserver une trace datée de chaque communication, courriel ou téléversement.',
      'Préparer les traductions certifiées avant la dernière minute, surtout pour les actes d’état civil.',
      'Demander un avis professionnel si la situation est mixte (couple, enfants, statut transitoire).',
    ] },
    { kind: 'p', text: 'En cas de doute sérieux, un consultant réglementé en immigration ou un avocat spécialisé restent les seules sources fiables pour un cas particulier. Cet article est une lecture pédagogique, pas un avis juridique.' },
  ];
  const EN = [
    { kind: 'lede', text: article.dek },
    { kind: 'h2', text: 'Context, briefly' },
    { kind: 'p', text: 'This article draws on official IRCC publications and recognized provincial sources. The goal is not to predict the future, but to help you read the rules as they exist in May 2026, avoiding shortcuts often found on forums.' },
    { kind: 'p', text: 'Immigration programs change regularly. Each section below states when it was last verified and the points where a personal situation may shift the reading.' },
    { kind: 'h2', text: 'What the texts say' },
    { kind: 'p', text: 'Official guidelines set a fairly stable frame. Most refusals are not caused by a policy change but by an imprecise reading of the file at submission. We recommend reviewing the document list three times, at least a week apart.' },
    { kind: 'quote', text: 'A careful file does not guarantee a positive decision, but it almost always avoids refusals on administrative grounds.' },
    { kind: 'h2', text: 'Practical steps' },
    { kind: 'p', text: 'Before submitting, first list the official documents (passport, civil-status records, diplomas). Then add recently produced items (account statements, employment letters dated within six months, language test results). Finally, check that each piece matches exactly the list provided by the targeted program.' },
    { kind: 'h2', text: 'Going further' },
    { kind: 'list', items: [
      'Check the document list on the official IRCC site; beware of copies on other portals.',
      'Keep a dated record of every communication, email, or upload.',
      'Prepare certified translations early, especially for civil-status documents.',
      'Seek professional advice for mixed situations (couple, children, transitional status).',
    ] },
    { kind: 'p', text: 'In case of serious doubt, a regulated immigration consultant or a specialized lawyer remains the only reliable source for a particular case. This article is an educational reading, not legal advice.' },
  ];
  return lang === 'fr' ? FR : EN;
}

function ArticlePage({ article, articleIdx, allArticles, t, lang, ArticleArt, navigate }) {
  const body = buildArticleBody(article, lang);
  const related = allArticles.filter(a => a.tag === article.tag && a !== article).slice(0, 3);

  return (
    <article className="article-page">
      <div className="page-inner">
        <nav className="crumbs">
          <a href="#" onClick={(e) => { e.preventDefault(); navigate(''); }}>{lang==='fr'?'Accueil':'Home'}</a>
          <span className="crumb-sep">/</span>
          <a href={`#rubrique/${article.tag}`}>{article.cat}</a>
          <span className="crumb-sep">/</span>
          <span className="crumb-current">{lang==='fr'?'Article':'Article'}</span>
        </nav>

        <header className="article-head">
          <div className="detail-meta">
            <span className="badge">{article.cat}</span>
            <span className="meta-sep">/</span>
            <span className="card-mono">{article.date}</span>
            <span className="meta-sep">/</span>
            <span className="card-mono">{article.readTime} {t.minRead}</span>
          </div>
          <h1 className="article-title">{article.title}</h1>
          <p className="article-dek">{article.dek}</p>
        </header>

        <div className="article-hero">
          <ArticleArt kind={article.img} large/>
        </div>

        <div className="article-body">
          {body.map((b, i) => {
            if (b.kind === 'lede') return <p key={i} className="detail-lede">{b.text}</p>;
            if (b.kind === 'h2') return <h2 key={i}>{b.text}</h2>;
            if (b.kind === 'quote') return <blockquote key={i} className="detail-quote">{b.text}</blockquote>;
            if (b.kind === 'list') return <ul key={i} className="detail-list">{b.items.map((it, j) => <li key={j}>{it}</li>)}</ul>;
            return <p key={i}>{b.text}</p>;
          })}
        </div>

        {related.length > 0 && (
          <aside className="article-related">
            <span className="section-mono">{lang==='fr'?'À LIRE AUSSI':'RELATED READING'}</span>
            <div className="related-grid">
              {related.map((r, i) => {
                const idx = allArticles.indexOf(r);
                return (
                  <a key={i} href={`#article/${idx}`} className="related-card">
                    <div className="related-art"><ArticleArt kind={r.img}/></div>
                    <div className="related-meta"><span className="badge badge-sm">{r.cat}</span><span className="card-mono">{r.readTime} {t.minRead}</span></div>
                    <h4 className="related-title">{r.title}</h4>
                  </a>
                );
              })}
            </div>
          </aside>
        )}

        <div className="back-bar">
          <a href={`#rubrique/${article.tag}`} className="btn-ghost">
            ← {lang==='fr'?'Retour à la rubrique':'Back to section'}
          </a>
        </div>
      </div>
    </article>
  );
}

function TopicPage({ topic, allArticles, t, lang, ArticleArt, navigate }) {
  const articles = allArticles.filter(a => a.tag === topic.id);

  return (
    <article className="topic-page">
      <div className="page-inner">
        <nav className="crumbs">
          <a href="#" onClick={(e) => { e.preventDefault(); navigate(''); }}>{lang==='fr'?'Accueil':'Home'}</a>
          <span className="crumb-sep">/</span>
          <span className="crumb-current">{topic.title}</span>
        </nav>

        <header className="topic-page-head">
          <span className="section-mono">{lang==='fr'?'RUBRIQUE · ':'SECTION · '}{topic.kicker}</span>
          <h1 className="article-title">{topic.title}</h1>
          <p className="article-dek">{topic.desc}</p>
          <div className="topic-stats">
            <span className="card-mono">
              {articles.length} {articles.length > 1 ? (lang==='fr'?'articles':'articles') : 'article'}
            </span>
          </div>
        </header>

        <div className="topic-page-grid">
          {articles.map((a) => {
            const idx = allArticles.indexOf(a);
            return (
              <a key={idx} href={`#article/${idx}`} className="article-card">
                <div className="card-art"><ArticleArt kind={a.img}/></div>
                <div className="card-body">
                  <div className="card-meta">
                    <span className="badge badge-sm">{a.cat}</span>
                    <span className="card-mono">{a.readTime} {t.minRead}</span>
                  </div>
                  <h4 className="card-title">{a.title}</h4>
                  <p className="card-dek">{a.dek}</p>
                  <div className="card-foot">
                    <span className="card-mono">{a.date}</span>
                    <span className="card-arrow">→</span>
                  </div>
                </div>
              </a>
            );
          })}
        </div>

        <div className="back-bar">
          <a href="#" onClick={(e) => { e.preventDefault(); navigate(''); }} className="btn-ghost">
            ← {lang==='fr'?'Retour à l’accueil':'Back to home'}
          </a>
        </div>
      </div>
    </article>
  );
}

Object.assign(window, { ArticlePage, TopicPage, buildArticleBody });

// ─── Static pages (About, Privacy, Contact) ───────────────────────────────
function StaticPage({ pageId, lang, navigate }) {
  const CONTENT = {
    about: {
      fr: {
        crumb: 'À propos',
        title: 'À propos de Canadian Portal',
        dek: 'Un journal indépendant pour préparer un projet canadien avec calme.',
        body: [
          _h2('Notre mission'),
          _p('Canadian Portal publie des guides pédagogiques sur l’immigration, le travail, la vie au Canada et la citoyenneté. Notre rôle n’est pas de remplacer les sources officielles ni les professionnels réglementés. Nous existons pour rendre les règles plus lisibles, étape par étape.'),
          _h2('Indépendance et neutralité'),
          _p('Canadian Portal n’a aucun lien avec le gouvernement du Canada, IRCC, ou un quelconque gouvernement provincial. Aucune publication n’est commanditée par un consultant en immigration, un avocat ou un cabinet. Les articles sont produits par notre rédaction et révisés au moment de chaque changement officiel.'),
          _h2('Méthode éditoriale'),
          _p('Chaque guide est construit à partir des directives officielles publiées par IRCC ou par les gouvernements provinciaux. Les références secondaires (universités, ordres professionnels, médias canadiens reconnus) sont utilisées en appoint. Aucun article n’est rédigé à partir de forums anonymes.'),
          _h2('Limites de nos contenus'),
          _p('Cet ensemble de guides est pédagogique. Il ne constitue ni un avis juridique, ni une représentation devant IRCC. Pour les situations complexes, nous recommandons de consulter un consultant en immigration réglementé par le CICC ou un avocat membre du barreau canadien.'),
          _h2('Contact'),
          _p('Pour toute question ou correction factuelle, écrivez-nous via la page Contact. Nous lisons chaque message.'),
        ],
      },
      en: {
        crumb: 'About',
        title: 'About Canadian Portal',
        dek: 'An independent journal to plan a Canadian project calmly.',
        body: [
          _h2('Our mission'),
          _p('Canadian Portal publishes educational guides on immigration, work, life in Canada and citizenship. Our role is not to replace official sources or regulated professionals. We exist to make rules easier to read, step by step.'),
          _h2('Independence and neutrality'),
          _p('Canadian Portal has no ties with the Government of Canada, IRCC, or any provincial government. No publication is sponsored by an immigration consultant, lawyer or firm. Articles are produced by our editors and revised whenever an official change occurs.'),
          _h2('Editorial method'),
          _p('Each guide is built from official directives published by IRCC or by provincial governments. Secondary references (universities, professional bodies, reputable Canadian media) are used as backup. No article is written from anonymous forums.'),
          _h2('Limits of our content'),
          _p('This set of guides is educational. It does not constitute legal advice nor representation before IRCC. For complex situations, we recommend consulting an immigration consultant regulated by the CICC or a lawyer member of a Canadian bar.'),
          _h2('Contact'),
          _p('For any question or factual correction, write to us via the Contact page. We read every message.'),
        ],
      },
    },
    privacy: {
      fr: {
        crumb: 'Politique de confidentialité',
        title: 'Politique de confidentialité',
        dek: 'Comment Canadian Portal collecte et utilise les données.',
        body: [
          _h2('Informations collectées'),
          _p('Canadian Portal collecte un minimum de données : statistiques d’audience anonymes, adresses courriel pour les personnes qui s’abonnent volontairement à l’infolettre, et messages reçus via le formulaire de contact.'),
          _h2('Cookies et publicité'),
          _p('Le site utilise des cookies techniques et des cookies de mesure d’audience. Si une publicité est affichée, elle peut provenir de Google AdSense, qui utilise ses propres cookies conformément à sa politique. Vous pouvez gérer vos préférences via votre navigateur.'),
          _h2('Vos droits'),
          _p('Vous pouvez demander à tout moment l’accès, la rectification ou la suppression des données vous concernant en écrivant via la page Contact. Aucune donnée n’est revendue à des tiers commerciaux.'),
          _h2('Hébergement et sécurité'),
          _p('Les données sont hébergées sur des serveurs sécurisés au Canada ou dans l’Union européenne. Toutes les transmissions sont chiffrées en HTTPS.'),
          _h2('Modifications de la politique'),
          _p('Cette politique peut être mise à jour. La date de la dernière révision est indiquée en bas de page. Toute évolution majeure sera signalée en page d’accueil.'),
        ],
      },
      en: {
        crumb: 'Privacy Policy',
        title: 'Privacy Policy',
        dek: 'How Canadian Portal collects and uses data.',
        body: [
          _h2('Information collected'),
          _p('Canadian Portal collects a minimum of data: anonymous audience statistics, email addresses for people who voluntarily subscribe to the newsletter, and messages received via the contact form.'),
          _h2('Cookies and advertising'),
          _p('The site uses technical cookies and audience measurement cookies. If an advertisement is displayed, it may come from Google AdSense, which uses its own cookies in accordance with its policy. You can manage your preferences via your browser.'),
          _h2('Your rights'),
          _p('You may request at any time access to, correction or deletion of data concerning you by writing via the Contact page. No data is resold to commercial third parties.'),
          _h2('Hosting and security'),
          _p('Data is hosted on secure servers in Canada or the European Union. All transmissions are HTTPS-encrypted.'),
          _h2('Changes to this policy'),
          _p('This policy may be updated. The date of the latest revision is indicated at the bottom of the page. Any major change will be flagged on the home page.'),
        ],
      },
    },
    contact: {
      fr: {
        crumb: 'Contact',
        title: 'Contact',
        dek: 'Une question, une correction factuelle, une suggestion ?',
        body: [
          _h2('Nous écrire'),
          _p('La meilleure manière de joindre la rédaction est par courriel. Nous lisons chaque message et répondons généralement sous trois jours ouvrables.'),
          _p('Pour toute correction factuelle, merci d’indiquer le titre exact de l’article, le passage concerné, et la source officielle qui appuie votre demande.'),
          _h2('Adresse courriel'),
          _p('redaction@canadianportal.ca'),
          _h2('Ce que nous ne pouvons pas faire'),
          _p('Nous ne sommes pas un cabinet d’immigration. Nous ne pouvons pas évaluer un dossier individuel, prédire une décision d’IRCC, ni vous représenter. Pour ces démarches, consultez un consultant réglementé par le CICC ou un avocat membre d’un barreau canadien.'),
        ],
      },
      en: {
        crumb: 'Contact',
        title: 'Contact',
        dek: 'A question, a factual correction, a suggestion?',
        body: [
          _h2('Write to us'),
          _p('The best way to reach the editors is by email. We read every message and usually reply within three business days.'),
          _p('For any factual correction, please indicate the exact article title, the relevant passage, and the official source supporting your request.'),
          _h2('Email address'),
          _p('redaction@canadianportal.ca'),
          _h2('What we cannot do'),
          _p('We are not an immigration firm. We cannot evaluate an individual file, predict an IRCC decision, or represent you. For those steps, consult a consultant regulated by the CICC or a lawyer member of a Canadian bar.'),
        ],
      },
    },
  };
  const c = (CONTENT[pageId] || CONTENT.about)[lang] || (CONTENT[pageId] || CONTENT.about).fr;
  return (
    <article className="article-page">
      <div className="page-inner">
        <nav className="crumbs">
          <a href="#" onClick={(e) => { e.preventDefault(); navigate(''); }}>{lang==='fr'?'Accueil':'Home'}</a>
          <span className="crumb-sep">/</span>
          <span className="crumb-current">{c.crumb}</span>
        </nav>
        <header className="article-head">
          <h1 className="article-title">{c.title}</h1>
          <p className="article-dek">{c.dek}</p>
        </header>
        <div className="article-body">
          {c.body.map((b, i) => {
            if (b.kind === 'h2') return <h2 key={i}>{b.text}</h2>;
            return <p key={i}>{b.text}</p>;
          })}
        </div>
        <div className="back-bar">
          <a href="#" onClick={(e) => { e.preventDefault(); navigate(''); }} className="btn-ghost">
            ← {lang==='fr'?'Retour à l’accueil':'Back to home'}
          </a>
        </div>
      </div>
    </article>
  );
}

Object.assign(window, { StaticPage });
