// Typographic record-sleeve placeholder, original designs, no recreation.
// Each sleeve is generated from album metadata + optional sleeve spec.
// If a real cover image exists at covers/<rank>.jpg, it is rendered instead.
const { useMemo, useState: useSleeveState } = React;

// Ranks for which a real cover image has been uploaded to covers/<rank>.jpg.
// Update this set when you add more covers to the project.
const HAS_REAL_COVER = new Set([
  1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
  11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
  21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
  31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
  51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
  61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
  71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
  81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
  91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
]);

function hashStr(s) {
  let h = 0;
  for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0;
  return Math.abs(h);
}

const SLEEVE_PALETTES = [
  { bg: "#0a2540", fg: "#e9e2d0", accent: "#c97a3a" },
  { bg: "#2c1810", fg: "#d4a574", accent: "#a16207" },
  { bg: "#f4efe6", fg: "#1a1a1a", accent: "#b91c1c" },
  { bg: "#1a1f1a", fg: "#d4cfb8", accent: "#8a9b6e" },
  { bg: "#3d1f1f", fg: "#e8d5b7", accent: "#d97757" },
  { bg: "#1f2937", fg: "#fde68a", accent: "#f59e0b" },
  { bg: "#e8dfd0", fg: "#2b1d12", accent: "#7c2d12" },
  { bg: "#0e0e0e", fg: "#ededed", accent: "#dc2626" },
  { bg: "#2d3748", fg: "#e2e8f0", accent: "#ed8936" },
  { bg: "#4a2c2a", fg: "#f5e6d3", accent: "#c9a961" },
  { bg: "#1c2e3a", fg: "#e7dccc", accent: "#c87941" },
  { bg: "#302820", fg: "#d6c4a8", accent: "#7a9b76" },
];

const SLEEVE_STYLES = ["grid", "rule", "stamp", "bars", "spine", "center", "offset"];

function sleeveFor(album) {
  if (album.sleeve) {
    return {
      ...album.sleeve,
      style: album.sleeve.style || SLEEVE_STYLES[hashStr(album.title) % SLEEVE_STYLES.length],
    };
  }
  const pal = SLEEVE_PALETTES[hashStr(album.artist + album.title) % SLEEVE_PALETTES.length];
  const style = SLEEVE_STYLES[hashStr(album.title + album.year) % SLEEVE_STYLES.length];
  return { ...pal, style };
}

function Sleeve({ album, size = 280 }) {
  // Key on album identity, not rank — non-canon records all share rank -1, so a
  // rank-only dep would keep stale placeholder art when an instance is reused
  // for a different record (e.g. list re-sort/filter).
  const s = useMemo(() => sleeveFor(album), [album.slug, album.title, album.artist, album.rank]);
  const artist = album.artist.toUpperCase();
  const title = album.title.toUpperCase();
  const year = String(album.year);

  // Real cover art, preferred when we have one on disk. We render the <img>
  // unconditionally so the browser begins fetching immediately and only swap
  // back to the typographic sleeve if the load fails.
  const [imgFailed, setImgFailed] = useSleeveState(false);

  // A record added from the wider catalogue carries its cover as a URL
  // (Discogs / Cover Art Archive) rather than an on-disk slug file.
  if (album.coverUrl && !imgFailed) {
    return (
      <div style={{
        width: size, height: size, position: "relative", overflow: "hidden",
        flexShrink: 0, background: "#0a0a0a",
        boxShadow: "0 1px 0 rgba(0,0,0,.04), 0 20px 40px -24px rgba(0,0,0,.35)",
      }}>
        <img
          src={album.coverUrl}
          alt={album.title + " by " + album.artist + ", cover"}
          loading="lazy"
          decoding="async"
          width={size}
          height={size}
          onError={() => setImgFailed(true)}
          style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }}
        />
      </div>
    );
  }

  if (HAS_REAL_COVER.has(album.rank) && !imgFailed) {
    return (
      <div style={{
        width: size, height: size, position: "relative", overflow: "hidden",
        flexShrink: 0, background: "#0a0a0a",
        boxShadow: "0 1px 0 rgba(0,0,0,.04), 0 20px 40px -24px rgba(0,0,0,.35)",
      }}>
        <img
          src={"/covers/" + album.slug + ".jpg?v=2"}
          alt={album.title + " by " + album.artist + ", original cover"}
          loading="lazy"
          decoding="async"
          width={size}
          height={size}
          onError={() => setImgFailed(true)}
          style={{
            width: "100%", height: "100%", objectFit: "contain",
            display: "block",
          }}
        />
      </div>
    );
  }

  const wrap = {
    width: size, height: size, background: s.bg, color: s.fg,
    position: "relative", overflow: "hidden", flexShrink: 0,
    boxShadow: "0 1px 0 rgba(0,0,0,.04), 0 20px 40px -24px rgba(0,0,0,.35)",
  };

  // Shared title/artist typography
  const titleSize = size * (title.length > 18 ? 0.085 : title.length > 12 ? 0.11 : 0.14);

  if (s.style === "grid") {
    return (
      <div style={wrap}>
        <svg width={size} height={size} style={{ position: "absolute", inset: 0, opacity: 0.2 }}>
          {[...Array(12)].map((_, i) => (
            <line key={`h${i}`} x1="0" y1={(size * i) / 12} x2={size} y2={(size * i) / 12} stroke={s.fg} strokeWidth="0.5" />
          ))}
          {[...Array(12)].map((_, i) => (
            <line key={`v${i}`} x1={(size * i) / 12} y1="0" x2={(size * i) / 12} y2={size} stroke={s.fg} strokeWidth="0.5" />
          ))}
        </svg>
        <div style={{ position: "absolute", top: size * 0.08, left: size * 0.08, right: size * 0.08, fontFamily: "'Playfair Display', serif", fontSize: titleSize, lineHeight: 0.95, fontWeight: 900, letterSpacing: "-0.02em" }}>{title}</div>
        <div style={{ position: "absolute", bottom: size * 0.08, left: size * 0.08, right: size * 0.08, display: "flex", justifyContent: "space-between", alignItems: "flex-end", fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.04, letterSpacing: "0.1em" }}>
          <span>{artist}</span><span style={{ color: s.accent }}>{year}</span>
        </div>
      </div>
    );
  }

  if (s.style === "rule") {
    return (
      <div style={wrap}>
        <div style={{ position: "absolute", top: size * 0.1, left: size * 0.1, right: size * 0.1, fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.035, letterSpacing: "0.15em", opacity: 0.7 }}>VOL. {album.rank}</div>
        <div style={{ position: "absolute", top: size * 0.18, left: size * 0.1, right: size * 0.1, height: 2, background: s.accent }} />
        <div style={{ position: "absolute", top: size * 0.25, left: size * 0.1, right: size * 0.1, fontFamily: "'Playfair Display', serif", fontSize: titleSize, lineHeight: 0.95, fontWeight: 900, fontStyle: "italic" }}>{title}</div>
        <div style={{ position: "absolute", bottom: size * 0.18, left: size * 0.1, right: size * 0.1, height: 1, background: s.fg, opacity: 0.5 }} />
        <div style={{ position: "absolute", bottom: size * 0.08, left: size * 0.1, right: size * 0.1, fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.04, letterSpacing: "0.1em", display: "flex", justifyContent: "space-between" }}>
          <span>{artist}</span><span>{year}</span>
        </div>
      </div>
    );
  }

  if (s.style === "stamp") {
    return (
      <div style={wrap}>
        <div style={{ position: "absolute", inset: size * 0.08, border: `2px solid ${s.fg}`, opacity: 0.3 }} />
        <div style={{ position: "absolute", inset: size * 0.12, border: `1px solid ${s.accent}` }} />
        <div style={{ position: "absolute", top: size * 0.2, left: 0, right: 0, textAlign: "center", fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.035, letterSpacing: "0.25em" }}>— {album.rank.toString().padStart(3, '0')} —</div>
        <div style={{ position: "absolute", top: "50%", left: size * 0.14, right: size * 0.14, transform: "translateY(-50%)", textAlign: "center", fontFamily: "'Playfair Display', serif", fontSize: titleSize, lineHeight: 0.9, fontWeight: 900 }}>{title}</div>
        <div style={{ position: "absolute", bottom: size * 0.2, left: 0, right: 0, textAlign: "center", fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.04, letterSpacing: "0.2em", color: s.accent }}>{artist} · {year}</div>
      </div>
    );
  }

  if (s.style === "bars") {
    const bars = [0.2, 0.7, 0.35, 0.55, 0.9, 0.3, 0.75, 0.5];
    return (
      <div style={wrap}>
        <div style={{ position: "absolute", top: 0, left: 0, right: 0, bottom: size * 0.45, display: "flex", alignItems: "flex-end", padding: size * 0.08 }}>
          {bars.map((h, i) => (
            <div key={i} style={{ flex: 1, height: `${h * 100}%`, background: i % 3 === 0 ? s.accent : s.fg, opacity: i % 2 === 0 ? 1 : 0.6, marginRight: i < bars.length - 1 ? 2 : 0 }} />
          ))}
        </div>
        <div style={{ position: "absolute", bottom: size * 0.08, left: size * 0.08, right: size * 0.08, fontFamily: "'Playfair Display', serif", fontSize: titleSize, lineHeight: 0.95, fontWeight: 900 }}>{title}</div>
        <div style={{ position: "absolute", bottom: size * 0.02, left: size * 0.08, right: size * 0.08, fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.035, letterSpacing: "0.1em", opacity: 0.7 }}>{artist} / {year}</div>
      </div>
    );
  }

  if (s.style === "spine") {
    return (
      <div style={wrap}>
        <div style={{ position: "absolute", top: 0, bottom: 0, left: 0, width: size * 0.2, background: s.accent, display: "flex", alignItems: "center", justifyContent: "center" }}>
          <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.2, fontWeight: 700, color: s.bg, transform: "rotate(-90deg)", whiteSpace: "nowrap" }}>{album.rank}</div>
        </div>
        <div style={{ position: "absolute", top: size * 0.1, left: size * 0.3, right: size * 0.08, fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.035, letterSpacing: "0.15em", opacity: 0.8 }}>{year} · {album.genre ? album.genre.toUpperCase() : ""}</div>
        <div style={{ position: "absolute", top: size * 0.25, left: size * 0.3, right: size * 0.08, fontFamily: "'Playfair Display', serif", fontSize: titleSize * 0.9, lineHeight: 0.95, fontWeight: 900 }}>{title}</div>
        <div style={{ position: "absolute", bottom: size * 0.1, left: size * 0.3, right: size * 0.08, fontFamily: "'Playfair Display', serif", fontSize: size * 0.06, fontStyle: "italic", opacity: 0.8 }}>{album.artist}</div>
      </div>
    );
  }

  if (s.style === "center") {
    return (
      <div style={wrap}>
        <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center" }}>
          <div style={{ width: size * 0.4, height: size * 0.4, borderRadius: "50%", background: s.accent, display: "flex", alignItems: "center", justifyContent: "center" }}>
            <div style={{ width: size * 0.08, height: size * 0.08, borderRadius: "50%", background: s.bg }} />
          </div>
        </div>
        <div style={{ position: "absolute", top: size * 0.08, left: size * 0.08, right: size * 0.08, fontFamily: "'Playfair Display', serif", fontSize: titleSize, lineHeight: 0.95, fontWeight: 900 }}>{title}</div>
        <div style={{ position: "absolute", bottom: size * 0.08, left: size * 0.08, right: size * 0.08, fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.035, letterSpacing: "0.15em", textAlign: "right" }}>{artist} — {year}</div>
      </div>
    );
  }

  // offset
  return (
    <div style={wrap}>
      <div style={{ position: "absolute", top: size * 0.15, left: size * 0.15, right: size * 0.35, bottom: size * 0.5, background: s.accent, opacity: 0.8 }} />
      <div style={{ position: "absolute", top: size * 0.25, left: size * 0.25, right: size * 0.08, fontFamily: "'Playfair Display', serif", fontSize: titleSize, lineHeight: 0.95, fontWeight: 900, color: s.fg, mixBlendMode: "difference" }}>{title}</div>
      <div style={{ position: "absolute", bottom: size * 0.08, left: size * 0.08, right: size * 0.08, display: "flex", justifyContent: "space-between", alignItems: "flex-end" }}>
        <div style={{ fontFamily: "'Playfair Display', serif", fontSize: size * 0.055, fontStyle: "italic" }}>{album.artist}</div>
        <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: size * 0.05, letterSpacing: "0.1em" }}>{year}</div>
      </div>
    </div>
  );
}

Object.assign(window, { Sleeve, sleeveFor });
