// Supabase-backed content for the public site.
// Loaded after shared.jsx, before HomePage.jsx/GalleryPage.jsx — exposes window.sb + window.useCmsData().
// Credentials come from window.SUPABASE_CONFIG, set by config.js (gitignored — see config.example.js).
if (!window.SUPABASE_CONFIG) {
  throw new Error('Missing config.js — copy config.example.js to config.js and fill in your Supabase credentials.');
}

window.sb = supabase.createClient(window.SUPABASE_CONFIG.url, window.SUPABASE_CONFIG.anonKey);

// "2026-06-12" → "12 มิ.ย. 2569" (th-TH is Buddhist-era by default) / "12 Jun 2026".
// Returns null for empty/invalid input so callers can fall back to the legacy date_label text.
function formatPostDate(iso, locale) {
  if (!iso) return null;
  const d = new Date(`${iso}T00:00:00`);
  if (Number.isNaN(d.getTime())) return null;
  return d.toLocaleDateString(locale, { day: 'numeric', month: 'short', year: 'numeric' });
}

// Pure transform: raw table rows (plain arrays, same shape whether they came from a live
// query or the published JSON snapshot) → the shaped object every page component reads.
function shapeCmsData(raw) {
  const sections = raw.sections || [];
  const byType = {};
  sections.forEach((s) => { byType[s.type] = s; });

  const papersById = {};
  (raw.papers || []).forEach((p) => { papersById[p.id] = p; });
  const finishesById = {};
  (raw.finishes || []).forEach((f) => { finishesById[f.id] = f; });

  const galleryAll = (raw.galleryItems || []).map((g) => ({
    id: g.id,
    finishesTh: (g.finish_ids || []).map((id) => finishesById[id] && finishesById[id].name_th).filter(Boolean),
    finishesEn: (g.finish_ids || []).map((id) => finishesById[id] && (finishesById[id].name_en || finishesById[id].name_th)).filter(Boolean),
    paperTh: (papersById[g.paper_id] && papersById[g.paper_id].name_th) || g.paper_legacy,
    paperEn: (papersById[g.paper_id] && (papersById[g.paper_id].name_en || papersById[g.paper_id].name_th)) || g.paper_legacy,
    price: g.price,
    tone: g.tone,
    dark: g.dark,
    src: g.image_path || undefined,
    images: (g.images && g.images.length) ? g.images : undefined,
    angleCount: g.angle_count || undefined,
    homePosition: g.home_position,
    imagePosition: g.image_position || '50% 50%',
    imageZoom: g.image_zoom || 1,
  }));
  const galleryHome = galleryAll
    .filter((g) => g.homePosition !== null && g.homePosition !== undefined)
    .sort((a, b) => a.homePosition - b.homePosition);

  return {
    settings: raw.settings || null,
    typography: (raw.settings && raw.settings.typography) || (window.Typography && window.Typography.DEFAULTS) || {},
    sectionsOrdered: sections,
    sections: byType,
    tiers: (raw.tiers || []).map((t) => ({
      id: t.id,
      name: t.name_th, nameEn: t.name_en,
      fromPriceTh: t.from_price_th, fromPriceEn: t.from_price_en,
      href: t.href, ctaTh: t.cta_label_th, ctaEn: t.cta_label_en,
      placeholders: t.placeholders || [],
      // TierCard prioritises placeholders over src, so promote a single uploaded
      // image_path into `images` (slides) — slides always beat placeholders.
      images: (t.images && t.images.length) ? t.images : (t.image_path ? [t.image_path] : undefined),
      src: t.image_path || undefined, tone: t.tone,
      imagePosition: t.image_position || '50% 50%', imageZoom: t.image_zoom || 1,
    })),
    papers: (raw.papers || []).map((p) => ({
      id: p.id,
      nameTh: p.name_th, nameEn: p.name_en, gsm: p.gsm, tone: p.tone, dark: p.dark,
      textureTh: p.texture_th, textureEn: p.texture_en,
      images: (p.images && p.images.length) ? p.images : (p.image_path ? [p.image_path] : undefined),
      imagePosition: p.image_position || '50% 50%', imageZoom: p.image_zoom || 1,
    })),
    comparisonRows: (raw.comparisonRows || []).map((r) => ({
      id: r.id,
      th: r.label_th, en: r.label_en,
      std: r.cells && r.cells[0], prem: r.cells && r.cells[1], lux: r.cells && r.cells[2],
    })),
    blogPosts: (raw.blogPosts || []).map((b) => ({
      id: b.id,
      titleTh: b.title_th, titleEn: b.title_en,
      dateTh: formatPostDate(b.post_date, 'th-TH') || b.date_label,
      dateEn: formatPostDate(b.post_date, 'en-GB') || b.date_label,
      slug: b.slug, bodyTh: b.body_th, bodyEn: b.body_en,
      // A slug means the post has its own page here, so it wins — `href` is the fallback for
      // posts that live somewhere else entirely. Neither = a card that doesn't go anywhere.
      href: b.slug ? window.Shared.url(`/blog/${b.slug}`) : (b.href || undefined),
      tone: b.tone, src: b.image_path || undefined,
      images: (b.images && b.images.length) ? b.images : undefined,
      imagePosition: b.image_position || '50% 50%', imageZoom: b.image_zoom || 1,
    })),
    galleryItemsHome: galleryHome,
    galleryItemsAll: galleryAll,
    trustClients: (raw.trustClients || []).map((c) => (
      c.logo_path ? { src: c.logo_path, name: c.name } : c.name
    )),
  };
}
window.shapeCmsData = shapeCmsData;

// Draft = the live editable tables, straight from Supabase (what the builder edits).
async function loadDraft() {
  const sb = window.sb;
  const [sections, tiers, papers, finishes, comparisonRows, blogPosts, galleryItems, trustClients, settings] = await Promise.all([
    sb.from('sections').select('*').order('position'),
    sb.from('tiers').select('*').order('position'),
    sb.from('papers').select('*').order('position'),
    sb.from('finishes').select('*').order('position'),
    sb.from('comparison_rows').select('*').order('position'),
    sb.from('blog_posts').select('*').order('position'),
    sb.from('gallery_items').select('*').order('position'),
    sb.from('trust_strip_clients').select('*').order('position'),
    sb.from('site_settings').select('*').limit(1),
  ]);
  return {
    sections: sections.data || [],
    tiers: tiers.data || [],
    papers: papers.data || [],
    finishes: finishes.data || [],
    comparisonRows: comparisonRows.data || [],
    blogPosts: blogPosts.data || [],
    galleryItems: galleryItems.data || [],
    trustClients: trustClients.data || [],
    settings: (settings.data && settings.data[0]) || null,
  };
}

// Published = the frozen JSON snapshot written by the "Publish" button (publish_site() RPC).
// This is what every real visitor sees — edits in the builder never reach them until published.
async function loadPublished() {
  const { data } = await window.sb.from('site_snapshot').select('data').order('published_at', { ascending: false }).limit(1);
  const snap = (data && data[0] && data[0].data) || {};
  return {
    sections: snap.sections || [],
    tiers: snap.tiers || [],
    papers: snap.papers || [],
    finishes: snap.finishes || [],
    comparisonRows: snap.comparison_rows || [],
    blogPosts: snap.blog_posts || [],
    galleryItems: snap.gallery_items || [],
    trustClients: snap.trust_strip_clients || [],
    settings: snap.typography ? { typography: snap.typography } : null,
  };
}

function useCmsData() {
  const [data, setData] = React.useState(null);
  // Bumped when the builder host posts a `refresh` (editable.jsx dispatches `cms-refresh`),
  // so draft edits re-fetch. Inert on the public site (no one fires the event).
  const [version, setVersion] = React.useState(0);
  React.useEffect(() => {
    const onRefresh = () => setVersion((v) => v + 1);
    window.addEventListener('cms-refresh', onRefresh);
    return () => window.removeEventListener('cms-refresh', onRefresh);
  }, []);

  React.useEffect(() => {
    let cancelled = false;
    async function load() {
      const raw = window.EDIT_MODE ? await loadDraft() : await loadPublished();
      if (cancelled) return;
      setData(shapeCmsData(raw));
    }
    load();
    return () => { cancelled = true; };
  }, [version]);

  return data;
}

window.useCmsData = useCmsData;
