// Procedural placeholder artworks for mariusson.
// We don't load real artworks (copyright + offline); instead we render
// stylistically-distinct "art tiles" using deterministic SVG/canvas patterns,
// each tagged with European region/style/method/theme metadata so the
// taxonomy and Sunburst feel real.

// All 27 EU member states + a few cultural neighbours common in the European
// art circuit (UK, Norway, Switzerland, Iceland). Stored as full names so
// the wheel can read them directly.
const REGIONS = [
  // EU member states (27)
  'Austria', 'Belgium', 'Bulgaria', 'Croatia', 'Cyprus', 'Czechia',
  'Denmark', 'Estonia', 'Finland', 'France', 'Germany', 'Greece',
  'Hungary', 'Ireland', 'Italy', 'Latvia', 'Lithuania',
  'Luxembourg', 'Malta', 'Netherlands', 'Poland', 'Portugal',
  'Romania', 'Slovakia', 'Slovenia', 'Spain', 'Sweden',
  // Cultural neighbours
  'Iceland', 'Norway', 'Switzerland', 'United Kingdom',
];

const STYLES = ['Baroque', 'Romantic', 'Modernist', 'Abstract', 'Surreal', 'Brutalist', 'Conceptual', 'Figurative', 'Minimal', 'Expressionist'];
const METHODS = ['Oil', 'Watercolor', 'Charcoal', 'Photograph', 'Digital', 'Mixed Media', 'Etching', 'Sculpture', 'Ink', 'Collage'];
// Themes are abstract — they describe a work's *concern*, not its subject.
// Aligned with the workPalette themeShift map in atlas.jsx.
const THEMES = ['Solitude', 'The Body', 'Architecture', 'Memory', 'Land', 'Light', 'Decay', 'Ritual', 'Machine', 'Dream'];

// Seeded RNG (mulberry32)
function rng(seed) {
  let a = seed >>> 0;
  return () => {
    a |= 0; a = a + 0x6D2B79F5 | 0;
    let t = Math.imul(a ^ a >>> 15, 1 | a);
    t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
    return ((t ^ t >>> 14) >>> 0) / 4294967296;
  };
}

function hash(str) {
  let h = 2166136261 >>> 0;
  for (let i = 0; i < str.length; i++) {
    h ^= str.charCodeAt(i);
    h = Math.imul(h, 16777619);
  }
  return h >>> 0;
}

// Deterministic catalogue of N artworks
function buildCatalogue(count = 60) {
  const out = [];
  for (let i = 0; i < count; i++) {
    const r = rng(hash('art' + i));
    const region = REGIONS[Math.floor(r() * REGIONS.length)];
    const style = STYLES[Math.floor(r() * STYLES.length)];
    const method = METHODS[Math.floor(r() * METHODS.length)];
    const theme = THEMES[Math.floor(r() * THEMES.length)];
    const year = 1820 + Math.floor(r() * 205);
    const aw = 0.7 + r() * 0.6; // aspect 0.7..1.3
    const titleSeed = Math.floor(r() * 1000);
    out.push({
      id: 'AN-' + String(i).padStart(4, '0'),
      region, style, method, theme, year,
      aspect: aw,
      title: pickTitle(titleSeed, theme),
      artist: pickArtist(hash('artist' + i)),
      verified: r() > 0.55,
      price: r() > 0.5 ? Math.round(800 + r() * 24000) : null,
      seed: i,
    });
  }
  return out;
}

const TITLE_FRAGMENTS = [
  ['Untitled', 'Study', 'Portrait', 'Field', 'Interior', 'Notation', 'Vessel', 'After', 'Edge', 'Witness'],
  ['no.', '—', 'in', 'of', 'with', 'before', 'beside', 'as'],
  ['I', 'II', 'III', 'IV', 'V', 'VII', 'IX', 'XII', 'a Window', 'the River', 'Ash', 'Salt', 'Linen', 'Glass', 'Iron'],
];
function pickTitle(seed, theme) {
  const r = rng(seed);
  const a = TITLE_FRAGMENTS[0][Math.floor(r() * TITLE_FRAGMENTS[0].length)];
  const b = TITLE_FRAGMENTS[1][Math.floor(r() * TITLE_FRAGMENTS[1].length)];
  const c = TITLE_FRAGMENTS[2][Math.floor(r() * TITLE_FRAGMENTS[2].length)];
  const variants = [
    `${a}, ${theme}`,
    `${a} ${b} ${c}`,
    `${theme}, ${c}`,
    `${a} ${c}`,
  ];
  return variants[Math.floor(r() * variants.length)];
}

const FIRST = ['Elena', 'Marcus', 'Inge', 'Tomás', 'Ada', 'Lior', 'Maja', 'Cosmin', 'Nadia', 'Henrik', 'Saskia', 'Otto', 'Iris', 'Felix', 'Anouk', 'Bruno', 'Lina', 'Pavel', 'Soraya', 'Clio'];
const LAST = ['Vermeer', 'Janssens', 'Marchetti', 'Korhonen', 'Schiele', 'Larsson', 'Petrov', 'de Vries', 'Borges', 'Hoffmann', 'Albano', 'Carvalho', 'Novák', 'Halász', 'Lindqvist', 'Aaltonen'];
function pickArtist(seed) {
  const r = rng(seed);
  return `${FIRST[Math.floor(r() * FIRST.length)]} ${LAST[Math.floor(r() * LAST.length)]}`;
}

// ─────────────────────────────────────────────────────────────
// Procedural art tile — renders an "artwork" as SVG using a palette
// keyed by style. Looks varied enough to read as a gallery wall, but
// is deterministic per id.
// ─────────────────────────────────────────────────────────────
const PALETTES = {
  Baroque:        ['#1d1410', '#3a2516', '#7a4f2c', '#c69b6b', '#efe2c8'],
  Romantic:       ['#1a2334', '#2c3e5b', '#6b809e', '#c3b89e', '#e9dfc8'],
  Modernist:      ['#fafaf7', '#1a1a17', '#c14a32', '#dcd4bf', '#888377'],
  Abstract:       ['#f1ecdf', '#0e0e0c', '#a8351e', '#5e6f5a', '#d4c79b'],
  Surreal:        ['#e7d8c0', '#2a2540', '#7d5b8c', '#caa37a', '#1d1d22'],
  Brutalist:      ['#bfbcb3', '#3a3833', '#0e0e0c', '#797670', '#e3dfd4'],
  Conceptual:     ['#fafaf7', '#0e0e0c', '#fafaf7', '#0e0e0c', '#c14a32'],
  Figurative:     ['#efe1c8', '#3a261a', '#7a3f2a', '#c79c6b', '#1a1410'],
  Minimal:        ['#fafaf7', '#e8e3d6', '#d6cfb9', '#7a766b', '#0e0e0c'],
  Expressionist:  ['#1c1410', '#a83a1e', '#e8a23a', '#f1e3c0', '#3a2820'],
};

// ArtTile — renders a real artwork image when `work.image` is set
// (the public-domain catalogue from data/catalogue.json), otherwise falls
// back to the procedural SVG composition. The fallback path is preserved so
// works uploaded by users (no image yet) and any orphan calls still render.
function ArtTile({ work, width = 240, height, showMeta = false, style = {} }) {
  const w = work || { style: 'Minimal', region: '—', method: '—', seed: 0, aspect: 1 };
  const h = height || Math.round(width / (w.aspect || 1));
  const pal = PALETTES[w.style] || PALETTES.Minimal;

  if (w.image) {
    return (
      <div style={{
        width, height: h, position: 'relative',
        background: pal[0], overflow: 'hidden', ...style,
      }}>
        <img src={w.image} alt={w.title || ''} loading="lazy" decoding="async"
          draggable="false"
          style={{
            width: '100%', height: '100%',
            objectFit: 'cover',
            display: 'block', userSelect: 'none',
          }} />
        {showMeta && (
          <div className="meta" style={{
            position: 'absolute', left: 8, bottom: 6, right: 8,
            fontFamily: 'var(--mono)', fontSize: 9,
            letterSpacing: '0.1em', textTransform: 'uppercase',
            color: '#fafaf7',
            textShadow: '0 1px 2px rgba(0,0,0,0.55)',
            opacity: 0.9,
            display: 'flex', justifyContent: 'space-between',
            pointerEvents: 'none',
          }}>
            <span>{w.region} · {w.style}</span>
            <span>{w.year}</span>
          </div>
        )}
      </div>
    );
  }

  // ── Procedural fallback (placeholder / user-upload-without-image) ──
  const r = rng(hash('tile' + (w.seed ?? 0)));
  const family = pickFamily(w.style, r);
  return (
    <div style={{ width, height: h, position: 'relative', ...style }}>
      <svg viewBox={`0 0 ${width} ${h}`} width={width} height={h} preserveAspectRatio="none"
        style={{ display: 'block', background: pal[0] }}>
        {family === 'horizon' && <Horizon w={width} h={h} pal={pal} r={r} />}
        {family === 'fields' && <Fields w={width} h={h} pal={pal} r={r} />}
        {family === 'figure' && <Figure w={width} h={h} pal={pal} r={r} />}
        {family === 'grid' && <GridComp w={width} h={h} pal={pal} r={r} />}
        {family === 'gesture' && <Gesture w={width} h={h} pal={pal} r={r} />}
        {family === 'arch' && <Arch w={width} h={h} pal={pal} r={r} />}
        <rect x="0" y="0" width={width} height={h} fill="url(#grain)" opacity="0.06" />
        <defs>
          <filter id="grain">
            <feTurbulence type="fractalNoise" baseFrequency="1.6" numOctaves="2" />
            <feColorMatrix values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.6 0" />
          </filter>
          <pattern id="grain" patternUnits="userSpaceOnUse" width="100" height="100">
            <rect width="100" height="100" filter="url(#grain)" />
          </pattern>
        </defs>
      </svg>
      {showMeta && (
        <div className="meta" style={{
          position: 'absolute', left: 8, bottom: 6, right: 8,
          fontFamily: 'var(--mono)', fontSize: 9,
          letterSpacing: '0.1em', textTransform: 'uppercase',
          color: pal[0] === '#fafaf7' || pal[0] === '#efe1c8' || pal[0] === '#f1ecdf' || pal[0] === '#e7d8c0' || pal[0] === '#bfbcb3' ? '#0e0e0c' : '#fafaf7',
          opacity: 0.7,
          display: 'flex', justifyContent: 'space-between',
        }}>
          <span>{w.region} · {w.style}</span>
          <span>{w.year}</span>
        </div>
      )}
    </div>
  );
}

function pickFamily(style, r) {
  const map = {
    Baroque: ['figure', 'figure', 'arch'],
    Romantic: ['horizon', 'horizon', 'figure'],
    Modernist: ['fields', 'grid'],
    Abstract: ['fields', 'gesture'],
    Surreal: ['figure', 'fields'],
    Brutalist: ['arch', 'grid', 'arch'],
    Conceptual: ['grid', 'grid'],
    Figurative: ['figure', 'figure'],
    Minimal: ['fields', 'grid'],
    Expressionist: ['gesture', 'gesture', 'figure'],
  };
  const opts = map[style] || ['fields'];
  return opts[Math.floor(r() * opts.length)];
}

// Composition primitives ---------------------------------------------------

function Horizon({ w, h, pal, r }) {
  const horizon = h * (0.45 + r() * 0.25);
  return (
    <g>
      <rect x="0" y="0" width={w} height={horizon} fill={pal[1]} />
      <rect x="0" y={horizon} width={w} height={h - horizon} fill={pal[2]} />
      {/* sun/moon */}
      <circle cx={w * (0.3 + r() * 0.4)} cy={horizon - 12 - r() * 30} r={6 + r() * 14} fill={pal[3]} opacity="0.9" />
      {/* low landmass */}
      <path d={`M0 ${h} L0 ${horizon + 20} ${[...Array(8)].map((_, i) => `L${(w / 8) * (i + 1)} ${horizon + 20 + Math.sin(i * 1.2 + r() * 6) * 14}`).join(' ')} L${w} ${h} Z`} fill={pal[4]} opacity="0.85" />
      <path d={`M0 ${h} L0 ${horizon + 50} ${[...Array(10)].map((_, i) => `L${(w / 10) * (i + 1)} ${horizon + 50 + Math.sin(i * 0.8 + r() * 4) * 10}`).join(' ')} L${w} ${h} Z`} fill={pal[1]} opacity="0.8" />
    </g>
  );
}

function Fields({ w, h, pal, r }) {
  const cuts = 2 + Math.floor(r() * 3);
  const horizontal = r() > 0.5;
  const lines = [...Array(cuts)].map(() => r());
  lines.sort();
  return (
    <g>
      {[0, ...lines, 1].map((p, i, arr) => {
        if (i === arr.length - 1) return null;
        const next = arr[i + 1];
        const c = pal[(i + 1) % pal.length];
        return horizontal
          ? <rect key={i} x="0" y={p * h} width={w} height={(next - p) * h} fill={c} />
          : <rect key={i} x={p * w} y="0" width={(next - p) * w} height={h} fill={c} />;
      })}
      {/* one off-center accent shape */}
      <rect x={w * (0.1 + r() * 0.3)} y={h * (0.1 + r() * 0.3)}
        width={w * (0.2 + r() * 0.3)} height={h * (0.2 + r() * 0.3)}
        fill={pal[2]} opacity="0.85" />
    </g>
  );
}

function Figure({ w, h, pal, r }) {
  // Vague figure silhouette — a head and torso shape, painterly
  const cx = w * (0.4 + r() * 0.2);
  const cy = h * 0.42;
  const hr = Math.min(w, h) * (0.09 + r() * 0.04);
  return (
    <g>
      {/* atmospheric background */}
      <rect x="0" y="0" width={w} height={h} fill={pal[1]} />
      <ellipse cx={cx} cy={cy + hr * 1.4} rx={hr * 2.4} ry={hr * 0.6} fill={pal[2]} opacity="0.5" />
      {/* torso */}
      <path d={`M${cx - hr * 1.6} ${h} L${cx - hr * 1.2} ${cy + hr * 0.4} Q${cx} ${cy + hr * 1.6} ${cx + hr * 1.2} ${cy + hr * 0.4} L${cx + hr * 1.6} ${h} Z`} fill={pal[3]} />
      {/* head */}
      <circle cx={cx} cy={cy} r={hr} fill={pal[3]} />
      {/* shadow side */}
      <path d={`M${cx} ${cy - hr} A${hr} ${hr} 0 0 0 ${cx} ${cy + hr} Z`} fill={pal[1]} opacity="0.4" />
      {/* highlight */}
      <ellipse cx={cx + hr * 0.3} cy={cy - hr * 0.3} rx={hr * 0.3} ry={hr * 0.4} fill={pal[4]} opacity="0.5" />
    </g>
  );
}

function GridComp({ w, h, pal, r }) {
  const rows = 3 + Math.floor(r() * 4);
  const cols = 3 + Math.floor(r() * 4);
  return (
    <g>
      <rect x="0" y="0" width={w} height={h} fill={pal[0]} />
      {[...Array(rows * cols)].map((_, i) => {
        const x = (i % cols) * (w / cols);
        const y = Math.floor(i / cols) * (h / rows);
        const fill = pal[Math.floor(rng(hash('g' + i + r()))() * pal.length)];
        const fillProb = rng(hash('gp' + i))();
        if (fillProb < 0.4) return null;
        return <rect key={i} x={x + 2} y={y + 2} width={w / cols - 4} height={h / rows - 4} fill={fill} opacity={0.8 + fillProb * 0.2} />;
      })}
    </g>
  );
}

function Gesture({ w, h, pal, r }) {
  return (
    <g>
      <rect x="0" y="0" width={w} height={h} fill={pal[0]} />
      {[...Array(6)].map((_, i) => {
        const sx = r() * w, sy = r() * h;
        const cx = r() * w, cy = r() * h;
        const ex = r() * w, ey = r() * h;
        return (
          <path key={i}
            d={`M${sx} ${sy} Q${cx} ${cy} ${ex} ${ey}`}
            stroke={pal[1 + Math.floor(r() * (pal.length - 1))]}
            strokeWidth={2 + r() * 18}
            fill="none"
            strokeLinecap="round"
            opacity={0.5 + r() * 0.5}
          />
        );
      })}
    </g>
  );
}

function Arch({ w, h, pal, r }) {
  const cx = w / 2;
  const archW = w * (0.4 + r() * 0.3);
  const archH = h * (0.55 + r() * 0.2);
  return (
    <g>
      <rect x="0" y="0" width={w} height={h} fill={pal[1]} />
      <rect x={(w - archW) / 2} y={h - archH} width={archW} height={archH - archW / 2} fill={pal[3]} />
      <ellipse cx={cx} cy={h - archH + archW / 2 - archW / 2} rx={archW / 2} ry={archW / 2} fill={pal[3]} />
      <rect x={(w - archW * 0.6) / 2} y={h - archH * 0.6} width={archW * 0.6} height={archH * 0.6 - archW * 0.3} fill={pal[2]} />
      <ellipse cx={cx} cy={h - archH * 0.6 + archW * 0.3 - archW * 0.3} rx={archW * 0.3} ry={archW * 0.3} fill={pal[2]} />
      {/* floor shadow */}
      <rect x="0" y={h - 8} width={w} height="8" fill={pal[4]} opacity="0.4" />
    </g>
  );
}

Object.assign(window, {
  REGIONS, STYLES, METHODS, THEMES,
  buildCatalogue, ArtTile, PALETTES,
});
