// Shared components: SourceBadge, Stars, ReviewCard, FilterBar.

const SOURCES = window.SOURCES;

function Stars({ rating, size = 13 }) {
  const full = Math.round(rating);
  return (
    <span className="stars" aria-label={`${rating} out of 5 stars`}>
      {[1,2,3,4,5].map(i => (
        <svg key={i} width={size} height={size} viewBox="0 0 14 14" fill={i <= full ? "currentColor" : "none"}
             stroke={i <= full ? "none" : "currentColor"} strokeWidth="1" className={i > full ? "empty" : ""}>
          <path d="M7 1.2 8.7 5l4.2.5-3.1 2.9.8 4.1L7 10.6 3.4 12.5l.8-4.1L1.1 5.5 5.3 5z" />
        </svg>
      ))}
    </span>
  );
}

function SourceBadge({ source, style = "pill" }) {
  const s = SOURCES[source];
  if (!s) return null;
  if (style === "pill") {
    return (
      <span className="sb" data-style="pill" style={{ background: s.color }}>
        <SourceGlyph source={source} />
        <span className="sb-name">{s.label}</span>
      </span>
    );
  }
  if (style === "outline") {
    return (
      <span className="sb" data-style="outline" style={{ color: s.color }}>
        <SourceGlyph source={source} />
        <span className="sb-name">{s.label}</span>
      </span>
    );
  }
  if (style === "minimal") {
    return (
      <span className="sb" data-style="minimal" style={{ color: s.color }}>
        <span className="sb-name">{s.label}</span>
      </span>
    );
  }
  if (style === "dot") {
    return (
      <span className="sb" data-style="dot">
        <span className="sb-icon" style={{ background: s.color }}>{s.short}</span>
        <span className="sb-name">{s.label}</span>
      </span>
    );
  }
  return null;
}

// Simple geometric glyphs per source — original marks, not brand logos.
function SourceGlyph({ source }) {
  const common = { width: 11, height: 11, viewBox: "0 0 11 11", fill: "currentColor" };
  switch (source) {
    case "google":     return <svg {...common}><circle cx="5.5" cy="5.5" r="4.5" fill="none" stroke="currentColor" strokeWidth="1.8" /><path d="M5.5 5.5 H10" stroke="currentColor" strokeWidth="1.8" /></svg>;
    case "trustpilot": return <svg {...common}><path d="M5.5 1 L6.8 4.2 H10.2 L7.5 6.2 L8.6 9.4 L5.5 7.5 L2.4 9.4 L3.5 6.2 L0.8 4.2 H4.2 Z" /></svg>;
    case "yelp":       return <svg {...common}><path d="M5.5 1 L8 4 V8 L5.5 10 L3 8 V4 Z" /></svg>;
    case "facebook":   return <svg {...common}><path d="M6 10V6h1.4l.2-1.6H6V3.5c0-.5.1-.8.8-.8h.8V1.3c-.4 0-.8-.1-1.4-.1-1.4 0-2.3.8-2.3 2.4v1H2.5V6h1.4v4z" /></svg>;
    case "bbb":        return <svg {...common}><path d="M3 2h3a1.5 1.5 0 0 1 0 3H3zm0 4h3.5a1.5 1.5 0 0 1 0 3H3z" stroke="currentColor" fill="none" strokeWidth="1" /></svg>;
    case "sitejabber": return <svg {...common}><path d="M2.5 3h6v2h-4v1.5h3.5v2H4.5V10h-2z" /></svg>;
    default:           return null;
  }
}

function VerifiedTick() {
  return (
    <svg className="verified-tick" viewBox="0 0 12 12" fill="none" aria-label="Verified">
      <circle cx="6" cy="6" r="6" fill="currentColor" opacity="0.18" />
      <path d="m3.5 6 1.8 1.7L8.5 4.6" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

function formatDate(iso) {
  const d = new Date(iso + "T00:00");
  return d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
}

function ReviewCard({ review, badgeStyle, variant = "card" }) {
  const [expanded, setExpanded] = React.useState(false);
  const longBody = review.body.length > 180;
  const className = variant === "feed" ? "card card-feed" : "card";

  return (
    <article className={className}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14 }}>
        <SourceBadge source={review.source} style={badgeStyle} />
        <span style={{ fontFamily: "var(--mono)", fontSize: 10.5, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: "0.04em" }}>
          {review.country}
        </span>
      </div>

      <div className="review-head">
        <div className="avatar">{review.initials}</div>
        <div className="review-who">
          <div className="review-name">
            {review.author}
            {review.verified && <VerifiedTick />}
          </div>
          <div className="review-meta">
            <Stars rating={review.rating} size={11} />
            <span className="sep">·</span>
            <span>{formatDate(review.date)}</span>
          </div>
        </div>
      </div>

      {review.title && <h3 className="review-title">{review.title}</h3>}

      <p className={"review-body" + (longBody && !expanded ? " clamped" : "")}>
        {review.body}
      </p>

      {longBody && (
        <button
          className="expand-btn"
          data-on={expanded ? "1" : "0"}
          onClick={() => setExpanded(v => !v)}
          aria-expanded={expanded}
        >
          {expanded ? "Show less" : "Read more"}
          <span className="chev" aria-hidden="true">
            <svg width="9" height="6" viewBox="0 0 9 6"><path d="M0 0h9L4.5 6z" fill="currentColor"/></svg>
          </span>
        </button>
      )}

      <div className="review-foot">
        <span>{review.service === "both" ? "PDF + Booklet" : review.service.toUpperCase()}</span>
        <span>↑ {review.helpful} helpful</span>
      </div>
    </article>
  );
}

function ListRow({ review, badgeStyle }) {
  const [expanded, setExpanded] = React.useState(false);
  const longBody = review.body.length > 220;
  return (
    <article className="card">
      <div>
        <div className="review-head" style={{ marginBottom: 8 }}>
          <div className="avatar">{review.initials}</div>
          <div className="review-who">
            <div className="review-name">{review.author}{review.verified && <VerifiedTick />}</div>
            <div className="review-meta"><Stars rating={review.rating} size={11} /></div>
          </div>
        </div>
        <SourceBadge source={review.source} style={badgeStyle} />
      </div>
      <div>
        {review.title && <h3 className="review-title" style={{ marginTop: 0 }}>{review.title}</h3>}
        <p className={"review-body" + (longBody && !expanded ? " clamped" : "")}>{review.body}</p>
        {longBody && (
          <button className="expand-btn" data-on={expanded ? "1" : "0"} onClick={() => setExpanded(v => !v)}>
            {expanded ? "Show less" : "Read more"}
            <span className="chev" aria-hidden="true">
              <svg width="9" height="6" viewBox="0 0 9 6"><path d="M0 0h9L4.5 6z" fill="currentColor"/></svg>
            </span>
          </button>
        )}
      </div>
      <div className="review-right">
        <div>{formatDate(review.date)}</div>
        <div style={{ marginTop: 6 }}>{review.country}</div>
        <div style={{ marginTop: 6, opacity: 0.6 }}>{review.service === "both" ? "PDF+Booklet" : review.service.toUpperCase()}</div>
      </div>
    </article>
  );
}

function FilterBar({ active, onChange, sort, onSort, counts, layout, onLayout }) {
  const allCount = Object.values(counts).reduce((a, b) => a + b, 0);
  return (
    <div className="filters">
      <span className="filter-label">Source</span>
      <button className="fchip" data-on={active === "all" ? "1" : "0"} onClick={() => onChange("all")}>
        All <span className="count">{allCount}</span>
      </button>
      {Object.entries(SOURCES).map(([key, src]) => (
        <button key={key} className="fchip" data-on={active === key ? "1" : "0"} onClick={() => onChange(key)}>
          <span className="dot" style={{ background: src.color }} />
          {src.label}
          <span className="count">{counts[key] || 0}</span>
        </button>
      ))}
      <span className="filter-spacer" />
      <div className="layout-switch" role="tablist" aria-label="Layout">
        {[
          { key: "masonry", icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor"><rect x="1" y="1" width="5" height="6"/><rect x="1" y="8" width="5" height="5"/><rect x="8" y="1" width="5" height="4"/><rect x="8" y="6" width="5" height="7"/></svg> },
          { key: "grid",    icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor"><rect x="1" y="1" width="5" height="5"/><rect x="8" y="1" width="5" height="5"/><rect x="1" y="8" width="5" height="5"/><rect x="8" y="8" width="5" height="5"/></svg> },
          { key: "feed",    icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor"><rect x="1" y="2" width="12" height="2"/><rect x="1" y="6" width="12" height="2"/><rect x="1" y="10" width="12" height="2"/></svg> },
          { key: "list",    icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor"><rect x="1" y="2" width="12" height="3"/><rect x="1" y="9" width="12" height="3"/></svg> },
        ].map(b => (
          <button key={b.key} data-on={layout === b.key ? "1" : "0"} onClick={() => onLayout(b.key)} aria-label={b.key}>
            {b.icon}
          </button>
        ))}
      </div>
      <select className="sort-select" value={sort} onChange={e => onSort(e.target.value)}>
        <option value="newest">Newest first</option>
        <option value="oldest">Oldest first</option>
        <option value="rating-high">Highest rated</option>
        <option value="rating-low">Lowest rated</option>
        <option value="helpful">Most helpful</option>
      </select>
    </div>
  );
}

Object.assign(window, {
  Stars, SourceBadge, SourceGlyph, VerifiedTick, ReviewCard, ListRow, FilterBar, formatDate,
});
