"use client";

import { useEffect, useState } from "react";

import { useBodyClass } from "@/lib/useBodyClass";

import type { LocaleCode } from "@/lib/locales";

/**
 * Popups and action bars for the current URL.
 *
 * These are resolved per URL and per request — a cached page would serve one
 * URL's targeting to another — so they cannot live in the ISR payload and are
 * fetched here instead, after paint.
 *
 * Code snippets come from the same endpoint but are deliberately NOT rendered
 * here. They are analytics and marketing tags, and running them after hydration
 * changes when they fire relative to page load, which breaks attribution. They
 * are resolved during the server render instead — see components/CodeSnippets.
 */
export default function PageContext({
  locale,
  path,
  enabled,
}: {
  locale: LocaleCode;
  path: string;
  /** False when the site has no active popup or action bar; skips the fetch. */
  enabled: boolean;
}) {
  const [data, setData] = useState<any>(null);

  /*
   * Reserves the bar's height. The Blade layout put this on <body> server-side
   * because it knew about the bar before rendering; here the bar is resolved
   * per-URL after paint, so the class arrives with it.
   */
  useBodyClass("has-action-bar", Boolean(data?.actionBar?.buttons?.length));

  useEffect(() => {
    if (!enabled) {
      return;
    }

    let cancelled = false;

    fetch(`/api/page-context?locale=${locale}&path=${encodeURIComponent(path)}`, {
      cache: "no-store",
    })
      .then((response) => (response.ok ? response.json() : null))
      .then((body) => {
        if (!cancelled) {
          setData(body);
        }
      })
      .catch(() => {
        // A failed popup fetch must never take the page with it.
      });

    return () => {
      cancelled = true;
    };
  }, [locale, path, enabled]);

  if (!data) {
    return null;
  }

  const bar = data.actionBar;

  return (
    <>
      {bar?.buttons?.length ? (
        <div className="action-bar" role="region" aria-label="Actions">
          <div className="container action-bar__inner">
            {/*
              `.action-bar__actions` wrapping `.btn` elements, because that is
              what the stylesheet targets — every rule in the .action-bar block
              is written against `.btn` and `.btn--fill`. A class of its own
              here (`action-bar__button`) matched nothing at all and the bar
              rendered as two bare text links.
            */}
            <div className="action-bar__actions">
              {bar.buttons.map((button: any, index: number) => (
                <a
                  key={index}
                  // The API decides fill vs outline per button; anything that is
                  // not explicitly outline is filled, matching the backend's own
                  // default in ActionBar::resolvedButtons().
                  className={button.style === "outline" ? "btn" : "btn btn--fill"}
                  href={button.url ?? "#"}
                  target={button.target ?? undefined}
                  rel={button.target === "_blank" ? "noopener noreferrer" : undefined}
                >
                  {button.label}
                </a>
              ))}
            </div>
          </div>
        </div>
      ) : null}

      {(data.popups ?? []).map((popup: any) => (
        <div
          key={popup.id}
          className={`popup popup--${popup.variant ?? "default"}`}
          data-trigger={popup.trigger ?? undefined}
          data-trigger-value={popup.triggerValue ?? undefined}
          data-frequency={popup.frequency ?? undefined}
          hidden
        >
          {popup.eyebrow ? <p className="popup__eyebrow">{popup.eyebrow}</p> : null}
          <h2 className="popup__title">{popup.title}</h2>
          {popup.body ? <div className="popup__body">{popup.body}</div> : null}
          {popup.ctaUrl && popup.ctaLabel ? (
            <a className="popup__cta" href={popup.ctaUrl}>
              {popup.ctaLabel}
            </a>
          ) : null}
        </div>
      ))}
    </>
  );
}
