// cms.jsx — microCMS 連携レイヤー（本番用のデータ取得・変換）
// localStorage(store.jsx) の代わりに、microCMS のAPIから取得して
// アプリ内部の形に変換します。設定が無い/失敗した場合はサンプル表示にフォールバック。

// data.jsx が先に読み込まれている前提。そのサンプルを「予備データ」として退避。
const SAMPLE_PRODUCTS = (window.PRODUCTS || []).slice();
const SAMPLE_MASTERS = {
  makers: window.MAKERS || [], varieties: window.VARIETIES || [],
  origins: window.ORIGINS || [], shapes: window.SHAPES || [], hardness: window.HARDNESS || [],
};

// 硬さは microCMS では「商品内のセレクト」。絞り込み用に固定リストを用意。
const HARDNESS_FIXED = [
  { id: "硬い", name: "硬い" },
  { id: "ちょっと硬い", name: "ちょっと硬い" },
  { id: "ふつう", name: "ふつう" },
  { id: "ちょっとやわらかい", name: "ちょっとやわらかい" },
  { id: "やわらかい", name: "やわらかい" },
];

let __cache = null;  // 取得済み商品（内部形）

// ---- 共通計算（store.jsx と同じロジック）----
function costScore(per100, min, max) {
  if (!per100 || max === min) return 4.0;
  return Math.round((5 - 3 * (per100 - min) / (max - min)) * 10) / 10;
}
function withRanks(list) {
  const enriched = list.map((p) => ({
    ...p,
    pricePer100: p.weight ? Math.round((p.price / p.weight) * 100) : 0,
    reviewCount: (p.reviews || []).length,
  }));
  const pp = enriched.map((p) => p.pricePer100).filter((v) => v > 0);
  const min = pp.length ? Math.min(...pp) : 0;
  const max = pp.length ? Math.max(...pp) : 0;
  const scored = enriched.map((p) => {
    const scores = { ...p.scores, cost: costScore(p.pricePer100, min, max) };
    const vals = ["sweet", "aroma", "flavor", "cost"].map((k) => Number(scores[k]) || 0);
    const rating = Math.round((vals.reduce((s, v) => s + v, 0) / vals.length) * 10) / 10;
    return { ...p, scores, rating };
  });
  const sorted = [...scored].sort((a, b) =>
    (b.rating - a.rating) || (b.reviewCount - a.reviewCount) || (a.pricePer100 - b.pricePer100));
  const rankMap = {};
  sorted.forEach((p, i) => { rankMap[p.id] = i + 1; });
  return scored.map((p) => ({ ...p, rank: rankMap[p.id] }));
}

// app.jsx の refresh から呼ばれる。取得済みキャッシュ（無ければサンプル）を返す。
function loadProducts() {
  return withRanks(__cache && __cache.length ? __cache : SAMPLE_PRODUCTS);
}

// ---- microCMS 取得 ----
function cmsHeaders(cfg) { return { "X-MICROCMS-API-KEY": cfg.apiKey }; }
async function fetchList(cfg, endpoint, withDepth, orders) {
  const base = `https://${cfg.serviceDomain}.microcms.io/api/v1/${endpoint}`;
  const url = base + "?limit=100" + (withDepth ? "&depth=2" : "") + (orders ? "&orders=" + encodeURIComponent(orders) : "");
  const res = await fetch(url, { headers: cmsHeaders(cfg) });
  if (!res.ok) throw new Error(`${endpoint} の取得に失敗 (HTTP ${res.status})`);
  const json = await res.json();
  return json.contents || [];
}

// ---- 変換（microCMS → 内部形）----
const num = (v) => (v === "" || v == null ? 0 : Number(v));
const refId = (v) => (v && typeof v === "object" ? v.id : (v || ""));
const selVal = (v) => (Array.isArray(v) ? (v[0] || "") : (v || ""));
const imgUrl = (v) => (v && typeof v === "object" ? (v.url || "") : (v || ""));

// microCMS の画像は設定方法で形が変わる（単一画像 / 複数画像 / 繰り返しフィールド内の画像）。
// どの形でも画像URLを集められるよう、商品オブジェクト全体から画像URLを抽出する。
function isImageObj(v) {
  return v && typeof v === "object" && typeof v.url === "string" &&
    (v.height != null || v.width != null || /\.(jpe?g|png|webp|gif|avif)(\?|$)/i.test(v.url));
}
function collectImagesFrom(value, out) {
  if (!value) return;
  if (typeof value === "string") {
    if (/^https?:\/\//.test(value) && /\.(jpe?g|png|webp|gif|avif)(\?|$)/i.test(value)) out.push(value);
    return;
  }
  if (isImageObj(value)) { out.push(value.url); return; }
  if (Array.isArray(value)) { value.forEach((v) => collectImagesFrom(v, out)); return; }
  if (typeof value === "object") {
    // 繰り返しフィールドやカスタムフィールド内の画像を再帰的に探す
    Object.keys(value).forEach((k) => {
      if (["fieldId", "id"].includes(k)) return;
      collectImagesFrom(value[k], out);
    });
  }
}
function productImages(c) {
  const out = [];
  // よく使うフィールド名を優先（順序を安定させる）
  ["images", "image", "gallery", "photos", "画像", "商品画像"].forEach((k) => {
    if (c[k] !== undefined) collectImagesFrom(c[k], out);
  });
  // それでも見つからなければ全フィールドを走査
  if (out.length === 0) {
    Object.keys(c).forEach((k) => {
      if (["id", "createdAt", "updatedAt", "publishedAt", "revisedAt"].includes(k)) return;
      collectImagesFrom(c[k], out);
    });
  }
  return [...new Set(out)];  // 重複除去
}
function fmtDate(d) {
  if (!d) return "";
  const m = String(d).match(/^(\d{4})-(\d{2})-(\d{2})/);
  return m ? `${m[1]}.${m[2]}.${m[3]}` : String(d);
}
function adaptMaster(contents, extra) {
  return (contents || []).map((c) => {
    const o = { id: c.id, name: c.name || "" };
    (extra || []).forEach((k) => { if (c[k] !== undefined) o[k] = c[k]; });
    return o;
  });
}
function adaptProduct(c, idx) {
  return {
    id: c.id,
    _seq: idx,  // microCMS の取得順（既定で新しい登録が先頭）。新着判定に使用
    name: c.name || "",
    maker: refId(c.maker),
    variety: refId(c.variety),
    origin: refId(c.origin),
    shape: refId(c.shape),
    hardness: selVal(c.hardness),
    price: num(c.price),
    weight: num(c.weight),
    scores: { sweet: num(c.sweet), aroma: num(c.aroma), flavor: num(c.flavor) },
    tags: Array.isArray(c.tags) ? c.tags : [],
    badge: c.badge || "",
    imageUrl: (function () { const a = productImages(c); return a[0] || ""; })(),
    images: productImages(c),
    desc: c.desc || "",
    links: { rakuten: c.rakuten || "", amazon: c.amazon || "", official: c.official || "" },
    reviews: (c.reviews || []).map((r) => ({
      user: r.user || "管理人",
      date: fmtDate(r.date),
      body: r.body || "",
      images: (r.images || []).map(imgUrl).filter((u) => u),
    })),
  };
}

// ---- ステータス表示（画面下の小さな帯。正常時は出さない）----
function setBanner(msg, kind) {
  let el = document.getElementById("cms-banner");
  if (!msg) { if (el) el.remove(); return; }
  if (!el) {
    el = document.createElement("div");
    el.id = "cms-banner";
    document.body.appendChild(el);
  }
  el.className = "cms-banner " + (kind || "");
  el.innerHTML = `<span>${msg}</span><button onclick="this.parentNode.remove()" aria-label="閉じる">×</button>`;
}

// ---- 起動：CMS取得 → 成功でマウント／失敗でサンプル表示 ----
function useSample(reason) {
  window.MAKERS = SAMPLE_MASTERS.makers;
  window.VARIETIES = SAMPLE_MASTERS.varieties;
  window.ORIGINS = SAMPLE_MASTERS.origins;
  window.SHAPES = SAMPLE_MASTERS.shapes;
  window.HARDNESS = SAMPLE_MASTERS.hardness;
  __cache = SAMPLE_PRODUCTS.slice();
  window.PRODUCTS = withRanks(__cache);
  if (reason) setBanner("⚠️ " + reason + "（いまはサンプルデータを表示しています）", "warn");
  window.mountApp();
}

async function bootstrapFromCMS() {
  const cfg = window.CMS_CONFIG || {};
  const unset = !cfg.serviceDomain || !cfg.apiKey ||
    cfg.serviceDomain.indexOf("ここに") >= 0 || cfg.apiKey.indexOf("ここに") >= 0;
  if (unset) {
    useSample("microCMS未設定：cms-config.js にサービスIDとAPIキーを入力してください");
    return;
  }
  try {
    const [makers, varieties, origins, shapes, products] = await Promise.all([
      fetchList(cfg, "makers"),
      fetchList(cfg, "varieties"),
      fetchList(cfg, "origins"),
      fetchList(cfg, "shapes"),
      fetchList(cfg, "products", true, "-publishedAt"),
    ]);
    window.MAKERS = adaptMaster(makers, ["region", "since"]);
    window.VARIETIES = adaptMaster(varieties, ["note"]);
    window.ORIGINS = adaptMaster(origins, []);
    window.SHAPES = adaptMaster(shapes, ["note"]);
    window.HARDNESS = HARDNESS_FIXED;
    __cache = products.map(adaptProduct);
    // 画像が取得できているか、開発者ツールのConsoleで確認できるよう出力
    try {
      console.log("[干し芋ナビ] 取得した商品数:", products.length);
      if (products[0]) {
        console.log("[干し芋ナビ] 1件目の生データ:", products[0]);
        console.log("[干し芋ナビ] 1件目から抽出した画像URL:", productImages(products[0]));
      }
    } catch (e) { /* noop */ }    window.PRODUCTS = withRanks(__cache);
    setBanner("");
    window.mountApp();
  } catch (e) {
    useSample("microCMS接続エラー：" + (e && e.message ? e.message : e));
  }
}

Object.assign(window, { loadProducts, bootstrapFromCMS, __cmsWithRanks: withRanks });

// data.jsx 由来のグローバルを、取得完了まで暫定でサンプルにそろえておく
window.PRODUCTS = withRanks(SAMPLE_PRODUCTS);
