/* global IconWhatsApp, IconWebChat, IconVoice, IconLayers, IconInfinity, IconPencil, IconWeb, IconInbox, IconMetaSocials, IconEmailOut, IconBrain */

/* ============================================================
 * THE OMNICHANNEL WHEEL
 *
 * From the "GuestMaker CRM Omnicanal" diagram (JUN26). Rebuilt rather than
 * embedded: the source is a flat PDF export in violet, with Spanish labels
 * and the Hotelinking lockup. Here it is real DOM — SVG for the rings and
 * spokes, HTML for every word — so it themes with the site, scales without
 * blurring, reads to a screen reader, and can be hovered.
 *
 * Placed directly after the problem section. That section ends on "hotels
 * don't lack tools, they lack a system"; this is the system, drawn. The
 * channel cards below it then detail the channels sitting on this rim.
 *
 * ELEVEN modules, which is the canonical count — the pricing page said
 * nine and showed six, and the homepage explore grid shows eight. This
 * diagram is the source of truth for the list; the others should follow it.
 *
 * Motion motif, unique to this section: RADIATION FROM THE CORE. Hovering a
 * module draws its spoke out from the centre and lights the node, while the
 * others recede — the point being that every module is fed by the same
 * brain. Transitions only, so unhover reverses and nothing loops.
 * ============================================================ */

const WHEEL = [
  { id: "whatsapp", label: "WhatsApp Automation", Ic: IconWhatsApp },
  { id: "b2b", label: "B2B CRM", Ic: IconBuilding },
  { id: "chatbot", label: "Web Chatbot", Ic: IconWebChat },
  { id: "callcenter", label: "AI Call Center", Ic: IconVoice },
  { id: "cdp", label: "CDP", Ic: IconLayers },
  { id: "loyalty", label: "Loyalty", Ic: IconInfinity },
  { id: "surveys", label: "Surveys", Ic: IconPencil },
  { id: "landing", label: "Landing Pages", Ic: IconWeb },
  { id: "inbox", label: "Email Inbox", Ic: IconInbox },
  { id: "meta", label: "Meta Socials", Ic: IconMetaSocials },
  { id: "email", label: "Email Marketing", Ic: IconEmailOut },
];

/* Translated from the diagram. "Motor de reservas" is the booking engine,
   "Criterios marca" is brand voice — not "brand criteria", which is what a
   literal pass gives you and which means nothing in English. */
const SOURCES = ["PMS", "WiFi portal", "Booking engine", "Channel manager", "Data lake", "CRM"];
const KNOWLEDGE = ["Web & app", "PDFs & docs", "Policies & rules", "Services & facilities", "FAQ", "Brand voice"];

const R = 41; // node ring radius, % of the square, leaves room for labels

const SectionWheel = () => {
  const [active, setActive] = useState(null);

  return (
    <section className="section-pad wheel" id="system-wheel">
      {/* Ground for the wheel. Without it the diagram floats on flat paper
          and reads as unfinished — it is mostly hairlines, so it needs
          something behind it to sit on. Two layers, both pointer-events
          none: a warm accent wash centred under the core, and a dot field
          masked to the corners, which is the one element of the source
          diagram's own composition worth keeping. */}
      <div className="wheel-wash" aria-hidden="true" />
      <div className="wheel-dots" aria-hidden="true" />
      <div className="container">
        <div className="wheel-head">
          <Reveal><div className="eyebrow">The system, drawn</div></Reveal>
          <Reveal delay={120}>
            <h2 className="h-1" style={{ marginTop: 24, maxWidth: 900 }}>
              Every surface a guest touches, <span className="italic-accent">run by one core.</span>
            </h2>
          </Reveal>
          <Reveal delay={220}>
            <p className="lead" style={{ marginTop: 26, maxWidth: 740 }}>
              Whether a guest messages, calls, books, replies to a campaign or fills in a survey, it is the same brain answering. The same guest record, the same knowledge, the same memory. Switch on a new surface and it arrives already knowing everything the others know.
            </p>
          </Reveal>
        </div>

        <Reveal delay={280}>
          <div className="wheel-stage" onMouseLeave={() => setActive(null)}>
            {/* Rings and spokes. aria-hidden because every word in the
                diagram is real text in the DOM below — the SVG carries no
                information of its own. */}
            <svg className="wheel-svg" viewBox="0 0 100 100" aria-hidden="true">
              <circle className="wheel-ring outer" cx="50" cy="50" r="47" />
              <circle className="wheel-ring track" cx="50" cy="50" r={R} />
              <circle className="wheel-ring core" cx="50" cy="50" r="27" />
              {WHEEL.map((m, i) => {
                const a = (i / WHEEL.length) * 2 * Math.PI - Math.PI / 2;
                return (
                  <line
                    key={m.id}
                    className={`wheel-spoke ${active === m.id ? "on" : ""}`}
                    x1={50 + Math.cos(a) * 27}
                    y1={50 + Math.sin(a) * 27}
                    x2={50 + Math.cos(a) * R}
                    y2={50 + Math.sin(a) * R}
                  />
                );
              })}
            </svg>

            {/* The core. Real HTML so the two lists are selectable text and
                inherit the site's type scale. */}
            <div className={`wheel-core ${active ? "dim" : ""}`}>
              <div className="wheel-core-badge">
                <IconBrain size={13} stroke={1.7} /> GuestMaker agentic AI
              </div>
              <div className="wheel-core-cols">
                <div>
                  <div className="wheel-core-h">Guest data</div>
                  <ul>{SOURCES.map((x) => <li key={x}>{x}</li>)}</ul>
                </div>
                <div>
                  <div className="wheel-core-h alt">Knowledge base</div>
                  <ul>{KNOWLEDGE.map((x) => <li key={x}>{x}</li>)}</ul>
                </div>
              </div>
            </div>

            <ul className="wheel-nodes">
              {WHEEL.map((m, i) => {
                const a = (i / WHEEL.length) * 2 * Math.PI - Math.PI / 2;
                const isOn = active === m.id;
                return (
                  <li
                    key={m.id}
                    className={`wheel-node ${isOn ? "on" : ""} ${active && !isOn ? "off" : ""}`}
                    /* Positioned by left/top as a share of the STAGE, not
                       by a percentage translate. A percentage translate
                       resolves against the ELEMENT's own box, and these are
                       0×0 points, so `translate(0, -41%)` moved nothing and
                       all eleven nodes stacked in the middle. The stage is
                       square, so equal left/top percentages keep the ring
                       circular — and with no rotation involved the labels
                       stay upright by construction. */
                    style={{
                      left: `${50 + Math.cos(a) * R}%`,
                      top: `${50 + Math.sin(a) * R}%`,
                    }}
                  >
                    <button
                      type="button"
                      onMouseEnter={() => setActive(m.id)}
                      onFocus={() => setActive(m.id)}
                      onBlur={() => setActive(null)}
                      aria-pressed={isOn}
                    >
                      <span className="wheel-node-dot"><m.Ic size={17} stroke={1.6} /></span>
                      <span className="wheel-node-label">{m.label}</span>
                    </button>
                  </li>
                );
              })}
            </ul>
          </div>
        </Reveal>
      </div>

      <style>{`
        .wheel {
          position: relative; overflow: hidden;
          background: var(--bg-elev-1);
          --e: cubic-bezier(0.22, 1, 0.36, 1);
        }
        /* The container has to win the stacking order or the wash paints
           over the diagram it is supposed to sit behind. */
        .wheel > .container { position: relative; z-index: 1; }
        .wheel-wash {
          position: absolute; inset: 0; pointer-events: none;
          /* --accent-glow is 22% accent. Across a 58%-wide ellipse that is
             not a glow, it is a filled pink disc that swallows the core
             panel — measured on screen, not guessed. These are single
             digits on purpose: the wheel is nearly all hairlines, so the
             ground has to be felt rather than seen. */
          background:
            radial-gradient(64% 52% at 50% 60%, color-mix(in srgb, var(--accent) 6%, transparent), transparent 66%),
            radial-gradient(40% 36% at 92% 4%, color-mix(in srgb, var(--accent) 5%, transparent), transparent 68%),
            radial-gradient(44% 40% at 3% 96%, color-mix(in srgb, var(--accent) 4%, transparent), transparent 68%);
        }
        /* Masked to opposite corners rather than tiled across the section —
           a full-bleed dot grid stops being texture and becomes pattern,
           and it would compete with the wheel's own dotted outer ring. */
        .wheel-dots {
          position: absolute; inset: 0; pointer-events: none;
          background-image: radial-gradient(var(--hairline) 1px, transparent 1.2px);
          background-size: 22px 22px;
          opacity: 0.75;
          -webkit-mask-image:
            radial-gradient(34% 30% at 96% 4%, #000 0%, transparent 72%),
            radial-gradient(34% 30% at 4% 96%, #000 0%, transparent 72%);
          mask-image:
            radial-gradient(34% 30% at 96% 4%, #000 0%, transparent 72%),
            radial-gradient(34% 30% at 4% 96%, #000 0%, transparent 72%);
          -webkit-mask-composite: source-over;
          mask-composite: add;
        }
        .wheel-head { margin-bottom: 56px; }

        .wheel-stage {
          position: relative;
          width: min(820px, 100%);
          margin: 0 auto;
          aspect-ratio: 1;
        }
        .wheel-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
        .wheel-ring { fill: none; stroke: var(--hairline); }
        .wheel-ring.outer { stroke-dasharray: 0.4 1.6; stroke-width: 0.35; opacity: 0.9; }
        .wheel-ring.track { stroke-width: 0.25; }
        .wheel-ring.core { stroke: var(--accent); stroke-width: 0.25; opacity: 0.45; }
        .wheel-spoke {
          stroke: var(--hairline);
          stroke-width: 0.25;
          transition: stroke 420ms var(--e), stroke-width 420ms var(--e);
        }
        .wheel-spoke.on { stroke: var(--accent); stroke-width: 0.6; }

        /* ---- core ---- */
        .wheel-core {
          position: absolute; top: 50%; left: 50%;
          transform: translate(-50%, -50%);
          width: 46%;
          text-align: center;
          transition: opacity 420ms var(--e);
        }
        .wheel-core.dim { opacity: 0.55; }
        .wheel-core-badge {
          display: inline-flex; align-items: center; gap: 7px;
          padding: 5px 12px; border-radius: 999px;
          border: 1px solid var(--accent);
          color: var(--accent);
          font-family: var(--f-mono);
          font-size: 9.5px; letter-spacing: 0.14em; text-transform: uppercase;
          white-space: nowrap;
        }
        .wheel-core-cols {
          display: grid; grid-template-columns: 1fr 1fr;
          gap: 18px; margin-top: 18px; text-align: left;
        }
        .wheel-core-h {
          font-family: var(--f-mono);
          font-size: 9px; letter-spacing: 0.14em; text-transform: uppercase;
          color: var(--accent);
          margin-bottom: 8px;
        }
        /* The source diagram uses a second hue for the knowledge column. The
           site has one accent, so the two columns separate on weight rather
           than by importing a colour that belongs to no token. */
        .wheel-core-h.alt { color: var(--ink-3); }
        .wheel-core-cols ul { list-style: none; margin: 0; padding: 0; }
        .wheel-core-cols li {
          font-size: 12px; line-height: 1.65; color: var(--ink-3);
          display: flex; gap: 6px;
        }
        .wheel-core-cols li::before {
          content: ""; flex-shrink: 0;
          width: 3px; height: 3px; border-radius: 999px;
          background: var(--hairline);
          margin-top: 8px;
        }

        /* ---- nodes ---- */
        .wheel-nodes { list-style: none; margin: 0; padding: 0; position: absolute; inset: 0; }
        .wheel-node { position: absolute; width: 0; height: 0; }
        .wheel-node button {
          position: absolute; top: 0; left: 0;
          transform: translate(-50%, -50%);
          display: flex; flex-direction: column; align-items: center; gap: 8px;
          background: none; border: none; padding: 0; cursor: pointer;
          font-family: inherit;
          transition: transform 420ms var(--e), opacity 420ms var(--e);
        }
        .wheel-node.on button { transform: translate(-50%, -50%) scale(1.09); }
        /* Rest is quiet, not empty — the unfocused nodes recede rather than
           disappear, so the wheel still reads as a whole while one is lit. */
        .wheel-node.off button { opacity: 0.42; }
        .wheel-node button:focus-visible { outline: 1px solid var(--accent); outline-offset: 6px; border-radius: 8px; }
        .wheel-node-dot {
          width: 52px; height: 52px; border-radius: 50%;
          display: flex; align-items: center; justify-content: center;
          background: var(--bg);
          border: 1px solid var(--hairline);
          color: var(--ink-3);
          transition: border-color 420ms var(--e), background 420ms var(--e),
                      color 420ms var(--e), box-shadow 420ms var(--e);
        }
        .wheel-node.on .wheel-node-dot {
          border-color: var(--accent);
          background: var(--accent);
          color: #fff;
          box-shadow: 0 0 0 6px var(--accent-glow);
        }
        .wheel-node-label {
          font-family: var(--f-mono);
          font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase;
          color: var(--ink-3);
          white-space: nowrap;
          transition: color 420ms var(--e);
        }
        .wheel-node.on .wheel-node-label { color: var(--accent); }

        /* A wheel does not survive a narrow column — the labels collide long
           before the circle stops fitting. Below this it becomes the list it
           always was, which loses the metaphor but keeps every word. */
        @media (max-width: 860px) {
          .wheel-stage { aspect-ratio: auto; width: 100%; }
          .wheel-svg { display: none; }
          .wheel-core {
            position: static; transform: none; width: 100%;
            text-align: left; padding: 22px;
            border: 1px solid var(--hairline); border-radius: 16px;
            background: var(--bg);
          }
          .wheel-core.dim { opacity: 1; }
          .wheel-nodes {
            position: static;
            display: grid; grid-template-columns: repeat(2, 1fr);
            gap: 14px; margin-top: 22px;
          }
          /* left/top are inline styles, so the static fallback has to
             neutralise them explicitly rather than rely on the cascade. */
          .wheel-node { position: static; width: auto; height: auto; inset: auto !important; }
          .wheel-node button,
          .wheel-node.on button { position: static; transform: none; flex-direction: row; gap: 11px; }
          .wheel-node.off button { opacity: 1; }
          .wheel-node-dot { width: 42px; height: 42px; }
          .wheel-node-label { white-space: normal; text-align: left; }
        }
        @media (max-width: 520px) {
          .wheel-nodes { grid-template-columns: 1fr; }
          .wheel-core-cols { grid-template-columns: 1fr; }
        }

        @media (prefers-reduced-motion: reduce) {
          .wheel-spoke, .wheel-core, .wheel-node button,
          .wheel-node-dot, .wheel-node-label {
            transition-duration: 1ms !important;
          }
        }
      `}</style>
    </section>
  );
};

window.SectionWheel = SectionWheel;
