// ABOUTME: Atelier core — design tokens, storage helpers, and small reusable UI atoms.
// ABOUTME: All exports attached to window for the rest of the JSX modules to consume.

const KOBO_PORTRAIT  = { w: 1264, h: 1680 };
const KOBO_LANDSCAPE = { w: 1680, h: 1264 };

const FONTS = [
  { id: "cormorant", name: "Cormorant", family: "'Cormorant Garamond', serif", weight: 500, italic: true,  sample: "The Court of Dreams" },
  { id: "cinzel",    name: "Cinzel",    family: "'Cinzel', serif",             weight: 500, italic: false, sample: "THE COURT OF DREAMS", letterSpacing: 0.08 },
  { id: "italiana",  name: "Italiana",  family: "'Italiana', serif",           weight: 400, italic: false, sample: "The Court of Dreams" },
  { id: "tangerine", name: "Tangerine", family: "'Tangerine', cursive",        weight: 700, italic: false, sample: "The Court of Dreams" },
  { id: "playfair",  name: "Playfair",  family: "'Playfair Display', serif",   weight: 500, italic: true,  sample: "The Court of Dreams" },
];

const COLORS = [
  { id: "starlight", value: "#fff8e0", name: "Starlight" },
  { id: "ember",     value: "#ffe2a8", name: "Ember"     },
  { id: "glow",      value: "#ecd2ff", name: "Glow"      },
  { id: "lavender",  value: "#c9a8e8", name: "Lavender"  },
  { id: "blush",     value: "#f5c2d9", name: "Blush"     },
  { id: "ink",       value: "#1a103e", name: "Ink"       },
];

const DIVIDERS = [
  { id: "none",    label: "None",     render: null     },
  { id: "stars3",  label: "✦ ✦ ✦",   render: "✦ ✦ ✦"  },
  { id: "fleur",   label: "❦",       render: "❦"      },
  { id: "diamond", label: "◆ ◆ ◆",   render: "◆ ◆ ◆"  },
  { id: "bullet",  label: "·  ·  ·", render: "·  ·  ·" },
];

const STORAGE_KEYS = {
  uploads: "velaris.uploads.v1",
  library: "velaris.library.v1",
  draft:   "velaris.draft.v1",
};

// ─────────────────────────────────────
// Storage helpers (small JSON in localStorage; photos go to IndexedDB)
// ─────────────────────────────────────
function loadJSON(key, fallback) {
  try { const v = localStorage.getItem(key); return v ? JSON.parse(v) : fallback; }
  catch { return fallback; }
}
function saveJSON(key, val) {
  try { localStorage.setItem(key, JSON.stringify(val)); } catch (e) { console.warn("[velaris] storage full", e); }
}

// ─────────────────────────────────────
// Scene-to-data-URL: rasterize a React-rendered SVG component for canvas export.
// ─────────────────────────────────────
function sceneToDataURL(SceneComp, id) {
  const wrap = document.createElement('div');
  wrap.style.cssText = 'position:absolute;left:-99999px;top:-99999px;width:1264px;height:1680px;';
  document.body.appendChild(wrap);
  const root = ReactDOM.createRoot(wrap);
  root.render(<SceneComp id={id || "exp"} />);
  return new Promise(resolve => {
    requestAnimationFrame(() => requestAnimationFrame(() => {
      const svgEl = wrap.querySelector('svg');
      if (!svgEl) { root.unmount(); wrap.remove(); resolve(null); return; }
      svgEl.setAttribute('preserveAspectRatio', 'xMidYMid slice');
      const xml = new XMLSerializer().serializeToString(svgEl);
      const blob = new Blob([xml], { type: 'image/svg+xml;charset=utf-8' });
      const url = URL.createObjectURL(blob);
      root.unmount();
      wrap.remove();
      resolve(url);
    }));
  });
}

// ─────────────────────────────────────
// UI atoms
// ─────────────────────────────────────
function Label({ children, style }) {
  return (
    <div style={{
      fontFamily: "'Cinzel', serif", fontSize: 10, letterSpacing: 3,
      color: "#c9a8e8", textTransform: "uppercase", ...style,
    }}>{children}</div>
  );
}

function TextField({ value, onChange, italic, placeholder, multiline }) {
  const commonStyle = {
    width: "100%", boxSizing: "border-box",
    padding: "10px 12px",
    background: "rgba(255,248,224,0.08)",
    border: "1px solid rgba(106,74,176,0.6)",
    borderRadius: 4, outline: "none",
    fontSize: 16, color: "#f5e9d3",
    fontFamily: "'Cormorant Garamond', serif",
    fontStyle: italic ? "italic" : "normal",
    resize: "vertical",
    lineHeight: 1.3,
  };
  if (multiline) {
    return (
      <textarea
        value={value}
        onChange={e => onChange(e.target.value)}
        placeholder={placeholder}
        rows={2}
        style={commonStyle}
      />
    );
  }
  return (
    <input
      value={value}
      onChange={e => onChange(e.target.value)}
      placeholder={placeholder}
      style={{ ...commonStyle, resize: undefined }}
    />
  );
}

function Slider({ value, min, max, step, onChange }) {
  const pct = ((value - min) / (max - min)) * 100;
  return (
    <div style={{ position: "relative", height: 18 }}>
      <div style={{ position: "absolute", top: 8, left: 0, right: 0, height: 2, background: "rgba(106,74,176,0.5)", borderRadius: 1 }} />
      <div style={{ position: "absolute", top: 8, left: 0, width: `${pct}%`, height: 2, background: "#c9a8e8", borderRadius: 1 }} />
      <input type="range" min={min} max={max} step={step} value={value}
        onChange={e => onChange(Number(e.target.value))}
        style={{ position: "absolute", inset: 0, width: "100%", height: "100%", opacity: 0, cursor: "pointer", margin: 0 }} />
      <div style={{
        position: "absolute", top: 3, left: `calc(${pct}% - 6px)`,
        width: 12, height: 12, borderRadius: 6, background: "#fff8e0",
        boxShadow: "0 0 10px rgba(201,168,232,0.8)", pointerEvents: "none",
      }} />
    </div>
  );
}

function FontPills({ value, onChange }) {
  return (
    <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
      {FONTS.map(f => {
        const active = f.id === value;
        return (
          <button key={f.id} onClick={() => onChange(f.id)} style={{
            padding: "5px 10px",
            fontSize: 10, fontFamily: "'Cinzel', serif", letterSpacing: 1.5,
            background: active ? "#c9a8e8" : "transparent",
            color: active ? "#1a103e" : "#c9a8e8",
            border: "1px solid rgba(201,168,232,0.6)",
            borderRadius: 999, cursor: "pointer",
          }}>{f.name.toUpperCase()}</button>
        );
      })}
    </div>
  );
}

function ColorSwatches({ value, onChange, customColor, onCustom }) {
  return (
    <div style={{ display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
      {COLORS.map(c => {
        const active = c.id === value;
        return (
          <button key={c.id} onClick={() => onChange(c.id)} title={c.name} style={{
            width: 24, height: 24, borderRadius: 12, background: c.value,
            border: active ? "2px solid #fff8e0" : "1px solid rgba(106,74,176,0.6)",
            boxShadow: active ? "0 0 8px rgba(201,168,232,0.8)" : "none",
            cursor: "pointer", padding: 0,
          }} />
        );
      })}
      <label title="Custom" style={{
        width: 24, height: 24, borderRadius: 12,
        background: `conic-gradient(from 0deg, #fff8e0, #ffe2a8, #ecd2ff, #c9a8e8, #f5c2d9, #fff8e0)`,
        border: value === "custom" ? "2px solid #fff8e0" : "1px solid rgba(106,74,176,0.6)",
        boxShadow: value === "custom" ? "0 0 8px rgba(201,168,232,0.8)" : "none",
        cursor: "pointer", position: "relative", overflow: "hidden",
      }}>
        <input type="color" value={customColor} onChange={e => { onCustom(e.target.value); onChange("custom"); }}
          style={{ position: "absolute", inset: 0, opacity: 0, cursor: "pointer" }} />
      </label>
    </div>
  );
}

function DividerPills({ value, onChange }) {
  return (
    <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
      {DIVIDERS.map(d => {
        const active = d.id === value;
        return (
          <button key={d.id} onClick={() => onChange(d.id)} style={{
            padding: "4px 9px",
            fontSize: 11, fontFamily: "'Cormorant Garamond', serif",
            background: active ? "#c9a8e8" : "transparent",
            color: active ? "#1a103e" : "#c9a8e8",
            border: "1px solid rgba(201,168,232,0.6)",
            borderRadius: 999, cursor: "pointer", minWidth: 28,
          }}>{d.label}</button>
        );
      })}
    </div>
  );
}

function Section({ label, children }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <Label>{label}</Label>
      {children}
    </div>
  );
}

function Toggle({ value, onChange, options }) {
  return (
    <div style={{
      display: "inline-flex", padding: 3, borderRadius: 999,
      background: "rgba(15,10,46,0.6)", border: "1px solid rgba(106,74,176,0.6)",
    }}>
      {options.map(o => (
        <button key={o.value} onClick={() => onChange(o.value)} style={{
          padding: "5px 14px", fontFamily: "'Cinzel', serif", fontSize: 10, letterSpacing: 2.5,
          background: value === o.value ? "#c9a8e8" : "transparent",
          color: value === o.value ? "#1a103e" : "#c9a8e8",
          border: "none", borderRadius: 999, cursor: "pointer",
        }}>{o.label}</button>
      ))}
    </div>
  );
}

Object.assign(window, {
  KOBO_PORTRAIT, KOBO_LANDSCAPE, FONTS, COLORS, DIVIDERS, STORAGE_KEYS,
  loadJSON, saveJSON, sceneToDataURL,
  Label, TextField, Slider, FontPills, ColorSwatches, DividerPills, Section, Toggle,
});
