/* ============================================================
   ЗАГРУЗКА КОНТЕНТА ИЗ CMS (Sanity)
   Датасет читается публично, без токенов: в браузер уходит только
   id проекта. Опубликованные документы видны всем, черновики — нет,
   поэтому у редактора есть нормальный цикл «правлю → публикую».

   Как это устроено: массивы PHOTO/ART/NOTES/FRIENDS из data.jsx
   остаются на месте и служат запасным вариантом. После загрузки
   их содержимое ЗАМЕНЯЕТСЯ ВНУТРИ ТЕХ ЖЕ объектов (length = 0 + push),
   потому что остальные файлы держат ссылку именно на них.
   Если CMS недоступна — сайт просто показывает встроенные данные.
   ============================================================ */

const SANITY_PROJECT = "6bi84947";
const SANITY_DATASET = "production";

/* тексты сайта: значения по умолчанию = то, что было в вёрстке */
const SITE = {
  logoName: "Вера Маркелова",
  logoSub: "Фото · Арт",
  homeTitle1: "архив",
  homeTitle2: "света",
  homeLead: "Плёночная фотография и рисунок.\nВера Маркелова — Москва.\nСнято на 35 мм и средний формат, 2022—2025.",
  eyebrow: "Избранное",
  indexTitle: "Фотография",
  indexLink: "Все плёночные работы →",
  photoLead: "Серия «У стены» — портреты у городских стен. Средний формат 6×6, дневной свет, минимум обработки.",
  artLead: "Этюды и работы на бумаге. Тушь, графит, акварель, уголь — ежедневная практика.",
};

/* размер и формат картинки задаём в самом URL — CDN отдаёт webp/avif
   и не увеличивает изображение сверх оригинала (fit=max) */
function cdnImage(url, w) {
  if (!url) return "";
  return url + "?w=" + (w || 1200) + "&q=80&auto=format&fit=max";
}

const WORK_FIELDS =
  '"id": _id, title, meta, ratio, label, desc, tone, ' +
  '"src": image.asset->url, "hot": image.hotspot{x, y}';

const GROQ = `{
  "site": *[_id=="siteText"][0]{logoName,logoSub,homeTitle1,homeTitle2,homeLead,
                                eyebrow,indexTitle,indexLink,photoLead,artLead},
  "photo": *[_type=="work" && kind=="photo"] | order(order asc){${WORK_FIELDS}},
  "art":   *[_type=="work" && kind=="art"]   | order(order asc){${WORK_FIELDS}},
  "notes": *[_type=="note"] | order(date desc){"id": _id, title, tag, excerpt, body, date},
  "artists": *[_type=="artist"] | order(order asc){
    "id": _id, name, role, note,
    "works": *[_type=="work" && kind=="friend" && artist._ref==^._id] | order(order asc){${WORK_FIELDS}}
  }
}`;

/* ISO-дата -> 12.03.2024 */
function ruDate(iso) {
  const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(String(iso || ""));
  return m ? m[3] + "." + m[2] + "." + m[1] : "";
}

function normWork(w) {
  return {
    id: w.id,
    title: w.title || "",
    meta: w.meta || "",
    ratio: w.ratio || "1:1",
    label: w.label || "",
    desc: w.desc || "",
    tone: typeof w.tone === "number" ? w.tone : 0.5,
    /* точка фокуса из Studio -> позиция кадрирования на сайте.
       Так автор сам решает, что не обрезать, когда пропорции не совпадают. */
    pos: w.hot && typeof w.hot.x === "number"
      ? Math.round(w.hot.x * 100) + "% " + Math.round(w.hot.y * 100) + "%"
      : "center",
    src: cdnImage(w.src),
  };
}

/* замена содержимого массива, не теряя саму ссылку на него */
function refill(target, items) {
  if (!Array.isArray(target) || !Array.isArray(items) || !items.length) return;
  target.length = 0;
  items.forEach((it) => target.push(it));
}

/* Берём api, а не apicdn: кэш CDN отдаёт старое содержимое ещё долго после
   правки, и редактор решил бы, что сайт сломался. Трафик тут небольшой,
   так что свежесть важнее кэша. */
function loadContent() {
  const url = "https://" + SANITY_PROJECT + ".api.sanity.io/v2024-01-01/data/query/" +
    SANITY_DATASET + "?query=" + encodeURIComponent(GROQ);

  return fetch(url)
    .then((r) => { if (!r.ok) throw new Error("CMS: HTTP " + r.status); return r.json(); })
    .then((json) => {
      const d = json.result || {};

      if (d.site) Object.keys(d.site).forEach((k) => { if (d.site[k]) SITE[k] = d.site[k]; });

      refill(PHOTO, (d.photo || []).map(normWork));
      refill(ART, (d.art || []).map(normWork));

      refill(NOTES, (d.notes || []).map((n) => ({
        id: n.id,
        date: ruDate(n.date),
        tag: n.tag || "",
        title: n.title || "",
        excerpt: n.excerpt || "",
        body: String(n.body || "").split(/\n\s*\n/).filter(Boolean),
      })));

      refill(FRIENDS, (d.artists || []).map((a) => ({
        id: a.id,
        name: a.name || "",
        role: a.role || "",
        note: a.note || "",
        works: (a.works || []).map(normWork),
      })));

      return true;
    })
    .catch((e) => {
      /* сайт продолжает работать на встроенных данных */
      if (window.console) console.warn("Контент из CMS не загружен:", e.message);
      return false;
    });
}

Object.assign(window, { SITE, loadContent, cdnImage });
