﻿// Common.jsx - componentes compartidos del periódico
const placeholderTones = ['blue', 'orange', 'dark', 'green', 'default'];

function pickTone(article) {
  if (!article) return 'default';
  const map = {
    'la-semanal': 'blue',
    'politica': 'blue',
    'economia': 'green',
    'nacionales': 'dark',
    'internacionales': 'dark',
    'deportes': 'blue',
    'tecnologia': 'dark',
    'opinion': 'orange',
    'cultura': 'orange',
    'vida-salud': 'green',
    'clima': 'blue',
  };
  return map[article.section] || 'default';
}

function ImagePlaceholder({ tone = 'default', caption, className = '', src }) {
  return (
    <div className={`cs-img-placeholder ${tone === 'default' ? '' : tone} ${src ? 'has-image' : ''} ${className}`}>
      {src && <img src={src} alt={caption || ''} loading="lazy" />}
      {caption && !src && <span className="caption">▸ {caption}</span>}
    </div>
  );
}

function SectionDot({ slug }) {
  const sec = window.CS_DATA.sections.find(s => s.slug === slug);
  return <span className="cs-section-dot" style={{ background: sec?.color || '#999' }}></span>;
}

function initials(value) {
  return String(value || 'CS')
    .split(/\s+/)
    .filter(Boolean)
    .slice(0, 2)
    .map(part => part[0])
    .join('')
    .toUpperCase() || 'CS';
}

function resolveAuthor(articleOrSlug) {
  const slug = typeof articleOrSlug === 'string' ? articleOrSlug : articleOrSlug?.author;
  const known = window.CS_DATA.authors[slug];
  if (known) return known;

  const name = typeof articleOrSlug === 'string'
    ? String(slug || 'Redacción')
    : articleOrSlug?.authorName || articleOrSlug?.author || 'Redacción';

  return {
    slug: slug || 'redaccion',
    name,
    role: articleOrSlug?.authorRole || 'Colaborador',
    bio: 'Periodista colaborador de Conexión Semanal.',
    avatar: initials(name),
    tone: 'amber',
    stats: { articles: 0, since: '2026' },
  };
}

function Kicker({ article, onClick }) {
  return (
    <span
      className={`cs-kicker cs-tag-${article.section} ${onClick ? 'is-link' : ''}`}
      onClick={onClick ? (e) => { e.stopPropagation(); onClick(); } : undefined}
    >
      {article.kicker}
    </span>
  );
}

function Byline({ authorSlug, date, readMin, onNav }) {
  const a = resolveAuthor(authorSlug);
  return (
    <div className="cs-hero-byline">
      <div className={`cs-avatar ${a.tone}`}>{a.avatar}</div>
      <div className="cs-byline-text">
        <div className="cs-byline-name" onClick={(e) => { e.stopPropagation(); onNav?.({ view: 'author', slug: a.slug }); }}>
          {a.name}
        </div>
        <div className="cs-byline-meta">{date} · {readMin} min de lectura</div>
      </div>
    </div>
  );
}

function ListItem({ article, onNav, showThumb = false }) {
  const a = resolveAuthor(article);
  return (
    <div className="cs-list-item" onClick={() => onNav({ view: 'article', id: article.id })}>
      <div>
        <div className="kicker-row">
          <SectionDot slug={article.section} />
          <span className={`cs-kicker cs-tag-${article.section}`}>{article.kicker}</span>
        </div>
        <h4>{article.title}</h4>
        <p>{article.dek}</p>
        <div className="meta-row">
          <span>{a?.name}</span>
          <span>·</span>
          <span>{article.date}</span>
          <span>·</span>
          <span>{article.readMin} min</span>
        </div>
      </div>
      {showThumb && (
        <div className="cs-list-thumb">
          <ImagePlaceholder src={article.imageUrl} tone={pickTone(article)} />
        </div>
      )}
    </div>
  );
}

function StripCard({ article, onNav }) {
  return (
    <div className="cs-strip-card" onClick={() => onNav({ view: 'article', id: article.id })}>
      <div className="image">
        <ImagePlaceholder src={article.imageUrl} tone={pickTone(article)} caption={`foto: ${article.section}`} />
      </div>
      <div className="kicker-row" style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
        <SectionDot slug={article.section} />
        <span className={`cs-kicker cs-tag-${article.section}`}>{article.kicker}</span>
      </div>
      <h3>{article.title}</h3>
      <p>{article.dek}</p>
    </div>
  );
}

function CatCard({ article, onNav }) {
  const a = resolveAuthor(article);
  return (
    <div className="cs-cat-card" onClick={() => onNav({ view: 'article', id: article.id })}>
      <div className="image"><ImagePlaceholder src={article.imageUrl} tone={pickTone(article)} caption={article.kicker.split(' · ')[0]} /></div>
      <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
        <SectionDot slug={article.section} />
        <span className={`cs-kicker cs-tag-${article.section}`}>{article.kicker}</span>
      </div>
      <h3>{article.title}</h3>
      <p>{article.dek}</p>
      <div className="meta-row" style={{ fontSize: 11.5, color: 'var(--mute)', fontFamily: 'var(--sans)', display: 'flex', gap: 8 }}>
        <span>{a?.name}</span><span>·</span><span>{article.date}</span><span>·</span><span>{article.readMin} min</span>
      </div>
    </div>
  );
}

function Footer({ onNav }) {
  const sections = window.CS_DATA.sections;
  return (
    <footer className="cs-footer">
      <div className="cs-container">
        <div className="cs-footer-grid">
          <div>
            <div className="cs-footer-brand">Conexión<br/><span>Semanal</span></div>
            <div className="cs-footer-tag">Periodismo Puro · Periodismo Real</div>
            <p>Un periódico digital dominicano comprometido con la verdad, la profundidad y el rigor. Desde Santo Domingo para toda la República y la diáspora.</p>
          </div>
          <div>
            <h5>Secciones</h5>
            <ul>
              {sections.slice(0, 6).map(s => (
                <li key={s.slug} onClick={() => onNav({ view: 'category', slug: s.slug })}>{s.name}</li>
              ))}
            </ul>
          </div>
          <div>
            <h5>Más</h5>
            <ul>
              {sections.slice(6).map(s => (
                <li key={s.slug} onClick={() => onNav({ view: 'category', slug: s.slug })}>{s.name}</li>
              ))}
              <li>Boletín</li>
              <li>Pódcast</li>
            </ul>
          </div>
          <div>
            <h5>Casa editorial</h5>
            <ul>
              <li>Quiénes somos</li>
              <li>Línea editorial</li>
              <li>Contacto</li>
              <li>Publicidad</li>
              <li>Código de ética</li>
              <li>Términos y privacidad</li>
            </ul>
          </div>
        </div>
        <div className="cs-footer-bottom">
          <span>© 2026 Conexión Semanal · Santo Domingo, República Dominicana</span>
          <span>Edición N.º 187 · Vol. IV</span>
        </div>
      </div>
    </footer>
  );
}

window.CS_Common = { ImagePlaceholder, SectionDot, Kicker, Byline, ListItem, StripCard, CatCard, Footer, pickTone, AnimatedNumber, AdSlot, resolveAuthor };

function getPublishedAd(size) {
  try {
    const ads = JSON.parse(localStorage.getItem('cs_admin_ads_live') || '[]');
    return ads.find(ad => ad && ad.status === 'active' && ad.placement === size && ad.imageUrl);
  } catch {
    return null;
  }
}

/* ===== AdSlot - espacio publicitario editorial =====
   Sizes follow IAB standards:
   - leaderboard: 970×90
   - billboard: 970×250
   - mediumRect: 300×250
   - halfPage: 300×600
   - mobile: 320×100
   - anuncio interno: 728×90
   - banner: 1180×180 (banner editorial de ancho completo)
*/
function AdSlot({ size = 'leaderboard', label = 'Anuncio institucional', sponsor, className = '', style = {} }) {
  const sizes = {
    leaderboard: { w: 970, h: 90, name: '970 × 90' },
    billboard:   { w: 970, h: 250, name: '970 × 250' },
    banner:      { w: 1180, h: 180, name: '1180 × 180' },
    mediumRect:  { w: 300, h: 250, name: '300 × 250' },
    halfPage:    { w: 300, h: 600, name: '300 × 600' },
    mobile:      { w: 320, h: 100, name: '320 × 100' },
    inline:      { w: 728, h: 90, name: '728 × 90' },
    square:      { w: 250, h: 250, name: '250 × 250' },
  };
  const s = sizes[size] || sizes.leaderboard;
  const publishedAd = getPublishedAd(size);
  const adContent = publishedAd ? (
    <div className="cs-ad-live">
      <img src={publishedAd.imageUrl} alt={publishedAd.title || publishedAd.client || 'Anuncio'} loading="lazy" />
      <div className="cs-ad-live-caption">
        <span>{publishedAd.client}</span>
      </div>
    </div>
  ) : (
    <>
      <div className="cs-ad-label">{label}</div>
      {sponsor && <div className="cs-ad-sponsor">{sponsor}</div>}
    </>
  );
  const inner = (
    <div className="cs-ad-frame">
      <div className="cs-ad-corner cs-ad-corner-tl">
        <span className="cs-ad-tag">› Espacio publicitario</span>
      </div>
      <div className="cs-ad-corner cs-ad-corner-tr">
        <span className="cs-ad-size">{s.name}</span>
      </div>
      <div className="cs-ad-inner">
        {adContent}
      </div>
      <div className="cs-ad-corner cs-ad-corner-bl">
        <span className="cs-ad-tag">Conexión Semanal · Pauta</span>
      </div>
    </div>
  );

  return (
    <div
      className={`cs-ad ${publishedAd ? 'has-live-ad' : ''} ${className}`}
      style={{
        '--ad-max-w': s.w + 'px',
        '--ad-h': s.h + 'px',
        ...style,
      }}
      aria-label="Espacio publicitario"
    >
      {publishedAd?.link ? (
        <a href={publishedAd.link} target="_blank" rel="noopener noreferrer" className="cs-ad-link">
          {inner}
        </a>
      ) : inner}
    </div>
  );
}

function AnimatedNumber({ value, duration = 900, format = (n) => String(n) }) {
  const [n, setN] = React.useState(0);
  const elRef = React.useRef(null);
  React.useEffect(() => {
    let raf = 0, started = false;
    const target = typeof value === 'number' ? value : parseFloat(value);
    if (isNaN(target)) { setN(value); return; }
    const startTs = performance.now();
    function tick(t) {
      const p = Math.min(1, (t - startTs) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setN(Math.round(target * eased * 10) / 10);
      if (p < 1) raf = requestAnimationFrame(tick);
    }
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [value, duration]);
  return <span className="cs-counter" ref={elRef}>{format(n)}</span>;
}

