/* eslint-disable */
// ---------------------------------------------------------------------------
// Site imagery served from Supabase Storage (public bucket).
//
// Storage-only: no table, no admin UI. You upload through the Supabase
// dashboard, the site reads by public URL. Public-bucket reads need NO API key,
// so nothing secret lives in this file.
//
// SETUP
//   1. Supabase dashboard > Storage > New bucket
//        name: site-images        public: ON
//   2. Paste your project ref below (Settings > General > Reference ID, or the
//      subdomain of your project URL: https://<ref>.supabase.co).
//   3. Upload files using the paths listed in IMAGE_PATHS at the bottom.
//
// Until the ref is filled in, or for any file not yet uploaded, the page shows
// a captioned placeholder rather than a broken image, so it stays presentable.
// ---------------------------------------------------------------------------

const SUPABASE_REF = "";              // e.g. "abcdefghijklmnopqrst"
const SUPABASE_BUCKET = "site-images";

// Public object URL. Storage serves these straight off the CDN.
function imageUrl(path) {
  if (!path) return null;
  if (/^(https?:)?\/\//.test(path)) return path;   // already absolute
  if (path.startsWith("assets/")) return path;      // bundled with the site
  if (!SUPABASE_REF) return null;                   // not configured yet
  return `https://${SUPABASE_REF}.supabase.co/storage/v1/object/public/` +
         `${SUPABASE_BUCKET}/${path.replace(/^\/+/, "")}`;
}

// An <img> that degrades to a captioned placeholder when the file is missing or
// Storage is unreachable. `fit` matches the old image-slot vocabulary: use
// "contain" for logos (cover crops them) and "cover" for photographs.
function SiteImage({ path, alt = "", caption, fit = "cover", className = "", rounded }) {
  const url = imageUrl(path);
  const [failed, setFailed] = React.useState(false);
  React.useEffect(() => { setFailed(false); }, [url]);

  if (!url || failed) {
    return (
      <div className={`img-ph ${className}`} data-rounded={rounded ? "1" : undefined}>
        <Icon name="image" size={20} />
        {caption && <span className="img-ph-cap">{caption}</span>}
      </div>
    );
  }
  return (
    <img
      className={`site-img ${className}`}
      src={url}
      alt={alt}
      loading="lazy"
      decoding="async"
      onError={() => setFailed(true)}
      style={{ objectFit: fit }}
      data-rounded={rounded ? "1" : undefined}
    />
  );
}

// ---------------------------------------------------------------------------
// The team roster lives in the bucket too, as team/team.json, so people can be
// added or removed without touching code or redeploying. The array compiled
// into the site is the fallback: if the file is missing, unreachable or
// malformed, the built-in list renders instead and the page is never empty.
// ---------------------------------------------------------------------------
const TEAM_MANIFEST = "team/team.json";

// Only entries with a usable name survive. A stray comma or a half-finished row
// therefore costs one person, not the whole page.
function sanitiseTeam(raw) {
  if (!Array.isArray(raw)) return [];
  const str = (v) => (typeof v === "string" ? v.trim() : "");
  return raw
    .filter((p) => p && typeof p === "object" && str(p.name))
    .map((p) => ({
      name: str(p.name),
      role: str(p.role),
      blurb: str(p.blurb),
      img: str(p.img) || null,
    }));
}

// Fetches the roster once on mount. The manifest is fetched uncached so a roster
// edit shows up immediately; the photos themselves stay on Storage's long cache.
function useTeamManifest(fallback) {
  const [team, setTeam] = React.useState(fallback);
  React.useEffect(() => {
    const url = imageUrl(TEAM_MANIFEST);
    if (!url) return;                       // Storage not configured yet
    let alive = true;
    fetch(`${url}?t=${Date.now()}`, { cache: "no-store" })
      .then((r) => (r.ok ? r.json() : Promise.reject(new Error("HTTP " + r.status))))
      .then((json) => {
        if (!alive) return;
        const clean = sanitiseTeam(json);
        if (clean.length) setTeam(clean);
        else console.warn(`[site-images] ${TEAM_MANIFEST} held no usable entries; using the built-in list.`);
      })
      .catch((e) => {
        console.warn(`[site-images] could not load ${TEAM_MANIFEST} (${e.message}); using the built-in list.`);
      });
    return () => { alive = false; };
  }, []);
  return team;
}

// ---------------------------------------------------------------------------
// The filenames to upload into the bucket. Keep this list as the contract
// between the site and Storage: add a person here and to ABOUT_TEAM, upload the
// matching file, done -- no redeploy needed for the image itself.
// ---------------------------------------------------------------------------
// Every team photo is now bundled with the site under assets/team/, so nothing
// in this build is waiting on a Storage upload. The roster itself can still be
// swapped at runtime via team/team.json -- see TEAM_MANIFEST above.
const IMAGE_PATHS = {};

Object.assign(window, { imageUrl, SiteImage, IMAGE_PATHS, SUPABASE_BUCKET,
                        TEAM_MANIFEST, sanitiseTeam, useTeamManifest });
