// Shared: tweaks hook, cart, album art placeholder, streaming audio player

// Global tweaks state with simple pub-sub so any consumer rerenders when
// the panel changes a value. Used by both the panel itself and components
// that need to read tweak values (e.g. CatalogueRow reading labelBadges).
window.__tweaksState = window.__tweaksState || {
  accent: '#c6311a',
  grain: true,
  labelBadges: true,
};
window.__tweaksListeners = window.__tweaksListeners || new Set();
window.__setTweaks = function (patch) {
  window.__tweaksState = { ...window.__tweaksState, ...patch };
  try { window.parent.postMessage({ type: '__edit_mode_set_keys', edits: patch }, '*'); } catch (e) {}
  window.__tweaksListeners.forEach(fn => fn());
};

window.useTweaks = function useTweaks() {
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "accent": "#c6311a",
    "grain": true,
    "labelBadges": true
  }/*EDITMODE-END*/;
  // Initialise the global once with the defaults from disk.
  React.useState(() => {
    if (!window.__tweaksInitialised) {
      window.__tweaksState = { ...TWEAK_DEFAULTS, ...window.__tweaksState };
      window.__tweaksInitialised = true;
    }
    return null;
  });
  // Force a rerender on changes.
  const [, force] = React.useReducer(x => x + 1, 0);
  React.useEffect(() => {
    window.__tweaksListeners.add(force);
    return () => window.__tweaksListeners.delete(force);
  }, []);

  const [editMode, setEditMode] = React.useState(false);
  React.useEffect(() => {
    const on = (e) => {
      if (e.data?.type === '__activate_edit_mode') setEditMode(true);
      else if (e.data?.type === '__deactivate_edit_mode') setEditMode(false);
    };
    window.addEventListener('message', on);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', on);
  }, []);
  return {
    tweaks: window.__tweaksState,
    setTweaks: window.__setTweaks,
    editMode,
  };
};

window.useCart = function useCart() {
  const [items, setItems] = React.useState([]);
  const add = (item) => setItems(prev => {
    const ex = prev.find(i => i.id === item.id && i.format === item.format);
    if (ex) return prev;
    return [...prev, item];
  });
  const remove = (id, fmt) => setItems(prev => prev.filter(i => !(i.id === id && i.format === fmt)));
  const clear = () => setItems([]);
  const total = items.reduce((s, i) => s + (i.price || 0), 0);
  return { items, add, remove, clear, total };
};

// Monolith-style album art. Uses real cover art if release.coverArt loads;
// otherwise falls back to the procedural placeholder below.
window.AlbumArt = function AlbumArt({ release, size = 240 }) {
  const s = size;
  const palette = release.palette || ["#111", "#333", "#ccc"];
  const [bg, mid, fg] = palette;
  const fmtLabel = window.MASSIVAN_HELPERS.formatLabel(release.format);

  // Probe the cover file: start 'loading' if a path is set, flip to 'ok' on
  // load, 'missing' on error. Missing → render procedural placeholder.
  const [coverState, setCoverState] = React.useState(release.coverArt ? 'loading' : 'missing');
  React.useEffect(() => {
    if (!release.coverArt) { setCoverState('missing'); return; }
    setCoverState('loading');
    const img = new Image();
    img.onload = () => setCoverState('ok');
    img.onerror = () => setCoverState('missing');
    img.src = release.coverArt;
  }, [release.coverArt]);

  if (coverState === 'ok') {
    return (
      <div style={{
        width: s, height: s, position: 'relative',
        background: bg, overflow: 'hidden',
        border: '1px solid rgba(255,255,255,0.08)',
        flexShrink: 0,
      }}>
        <img src={release.coverArt} alt={release.title}
          style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
      </div>
    );
  }

  return (
    <div style={{
      width: s, height: s, position: 'relative',
      background: bg, color: fg,
      overflow: 'hidden',
      border: '1px solid rgba(255,255,255,0.08)',
      flexShrink: 0,
    }}>
      <div style={{
        position: 'absolute', inset: 0,
        background: `repeating-linear-gradient(90deg, transparent 0 ${s/40}px, rgba(255,255,255,0.04) ${s/40}px ${s/20}px)`,
      }}/>
      <div style={{ position: 'absolute', top: s*0.06, left: s*0.06, right: s*0.06, display: 'flex', justifyContent: 'space-between', fontFamily: 'var(--mono)', fontSize: Math.max(9, s*0.04), letterSpacing: '0.12em', textTransform: 'uppercase', opacity: 0.7 }}>
        <span>{release.catNo || `MSV—${String(release.year).slice(-2)}`}</span>
        <span>{fmtLabel}</span>
      </div>
      {release.artist && release.artist !== 'Massivan' && (
        <div style={{
          position: 'absolute', left: s*0.06, right: s*0.06, top: s*0.18,
          fontFamily: 'var(--mono)', fontSize: Math.max(9, s*0.04), letterSpacing: '0.18em',
          textTransform: 'uppercase', opacity: 0.85,
        }}>{release.artist}</div>
      )}
      <div style={{
        position: 'absolute', left: s*0.06, right: s*0.06, bottom: s*0.2,
        fontFamily: 'var(--display)', fontSize: Math.max(16, s*0.12),
        lineHeight: 0.9, fontWeight: 800, letterSpacing: '-0.03em',
        textTransform: 'uppercase', color: fg,
      }}>{release.title}</div>
      <div style={{
        position: 'absolute', left: s*0.06, right: s*0.06, bottom: s*0.06,
        fontFamily: 'var(--mono)', fontSize: Math.max(9, s*0.035), letterSpacing: '0.14em', textTransform: 'uppercase', opacity: 0.7,
        display: 'flex', justifyContent: 'space-between',
      }}>
        <span>{release.tracks ? `${release.tracks} tr` : ''}</span>
        <span>{release.duration || ''}</span>
      </div>
      <div style={{
        position: 'absolute', top: s*0.35, right: -s*0.1,
        width: s*0.4, height: s*0.4, background: mid, mixBlendMode: 'screen',
      }}/>
    </div>
  );
};

// Bandcamp embed — large player iframe for own-label releases.
// Bandcamp's embed iframe expects an album/track numeric id. We don't have those
// until you paste them in (Bandcamp release page → Share / Embed → copy the
// `album=12345` or `track=67890` value into the release's `bandcampEmbed` field).
// Until then we render a styled "Open on Bandcamp" panel that links out.
window.BandcampEmbed = function BandcampEmbed({ release, compact }) {
  const embed = release.bandcampEmbed; // optional override: 'album=12345' or 'track=67890'
  if (embed) {
    const isAlbum = /^album=/.test(embed);
    if (compact) {
      // Small 42px-tall play-button + title strip, for inline use in cards/rows.
      const url = `https://bandcamp.com/EmbeddedPlayer/${embed}/size=small/bgcol=f2efe6/linkcol=c6311a/transparent=true/`;
      return (
        <iframe
          title={`${release.title} on Bandcamp`}
          src={url}
          style={{ border: 0, width: '100%', height: 42, display: 'block' }}
          seamless
        />
      );
    }
    const url = `https://bandcamp.com/EmbeddedPlayer/${embed}/size=large/bgcol=f2efe6/linkcol=c6311a/${isAlbum ? 'tracklist=true/' : ''}artwork=small/transparent=true/`;
    return (
      <iframe
        title={`${release.title} on Bandcamp`}
        src={url}
        style={{ border: 0, width: '100%', height: isAlbum ? 470 : 120, display: 'block', background: '#f2efe6' }}
        seamless
      />
    );
  }
  // No numeric ID yet → outbound CTA card
  return (
    <a href={release.bandcamp} target="_blank" rel="noopener noreferrer" style={{
      display: 'flex', alignItems: 'center', gap: 14, padding: 14,
      border: '1px solid var(--line)', textDecoration: 'none', color: 'inherit',
      background: '#fff',
    }}>
      <window.AlbumArt release={release} size={64}/>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.2em', textTransform: 'uppercase', opacity: 0.55 }}>Stream &amp; buy on Bandcamp</div>
        <div style={{ fontFamily: 'var(--display)', fontSize: 18, fontWeight: 700, letterSpacing: '-0.01em', textTransform: 'uppercase' }}>{release.title}</div>
      </div>
      <span style={{ background: '#1da0c3', color: '#fff', padding: '8px 14px', fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.15em', textTransform: 'uppercase', fontWeight: 700 }}>↗ Bandcamp</span>
    </a>
  );
};

// Bandcamp modal — centered popup with dimmed backdrop. Esc / backdrop / × closes.
function BandcampModal({ release, onClose }) {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    // Lock background scroll while modal is open
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = prevOverflow;
    };
  }, [onClose]);

  return (
    <div
      onClick={onClose}
      style={{
        position: 'fixed', inset: 0, zIndex: 100,
        background: 'rgba(10,10,10,0.72)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        padding: 20,
        fontFamily: 'var(--body)',
        animation: 'mvFadeIn 160ms ease-out',
      }}
    >
      <style>{`@keyframes mvFadeIn { from { opacity: 0 } to { opacity: 1 } }`}</style>
      <div
        onClick={(e) => e.stopPropagation()}
        style={{
          position: 'relative',
          width: '100%', maxWidth: 560,
          background: '#f2efe6', color: '#0a0a0a',
          border: '1px solid #0a0a0a',
          padding: 18,
          boxShadow: '0 30px 80px rgba(0,0,0,0.5)',
        }}
      >
        <div style={{
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          marginBottom: 14,
          fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase', opacity: 0.6,
        }}>
          <span>Bandcamp · {release.catNo || release.id}</span>
          <button onClick={onClose} aria-label="Close" style={{
            background: 'transparent', border: 'none', color: 'inherit', cursor: 'pointer',
            fontSize: 22, lineHeight: 1, padding: 0, opacity: 0.6,
          }}>×</button>
        </div>
        <window.BandcampEmbed release={release} />
      </div>
    </div>
  );
}

// Audio player — Bandcamp modal for own-label releases, Spotify card for
// licensed/external releases. Nothing else: no self-hosted MP3 fallback.
window.NowPlaying = function NowPlaying({ release, onClose }) {
  if (!release) return null;

  // Own-label releases on Bandcamp: centered modal popup, dimmed backdrop.
  if (window.MASSIVAN_HELPERS.hasBandcamp(release)) {
    return <BandcampModal release={release} onClose={onClose} />;
  }

  // External-label releases (or anything else): Spotify link card at bottom.
  return (
    <div style={{
      position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: 90,
      background: '#f2efe6', color: '#0a0a0a',
      borderTop: '1px solid #0a0a0a',
      padding: '10px 20px',
      display: 'flex', alignItems: 'center', gap: 14,
      fontFamily: 'var(--body)',
    }}>
      <div style={{ width: 40, height: 40, flexShrink: 0 }}>
        <window.AlbumArt release={release} size={40} />
      </div>
      <div style={{ minWidth: 0, flex: 1 }}>
        <div style={{ fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.2em', textTransform: 'uppercase', opacity: 0.55 }}>
          Licensed to {window.MASSIVAN_HELPERS.labelName(release)} · Listen on Spotify
        </div>
        <div style={{ fontWeight: 600, fontSize: 13, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{release.title}</div>
      </div>
      <a href={window.MASSIVAN_HELPERS.spotifyLink(release)} target="_blank" rel="noopener noreferrer" style={{
        background: '#1db954', color: '#000', padding: '8px 14px', textDecoration: 'none',
        fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.15em', textTransform: 'uppercase', fontWeight: 700,
      }}>▶ Spotify</a>
      <button onClick={onClose} style={{ background: 'transparent', border: 'none', color: 'inherit', opacity: 0.5, cursor: 'pointer', fontSize: 18, padding: 4 }}>×</button>
    </div>
  );
};
