#!/usr/bin/env bash
set -euo pipefail

PHPF="coproducer.php"
JSDIR="assets/js/modules"
JSF="$JSDIR/audio_master_strip.js"
STAMP="$(date +%Y%m%d_%H%M%S)"

mkdir -p "$JSDIR"
cp -p "$PHPF" "${PHPF}.bak_audio_master_${STAMP}"

cat > "$JSF" <<'JS'
/* audio_master_strip.js
   Master strip cloned from real mixer strip markup.
   - exact strip family look
   - placed at right end after Media
   - external module, isolated from main file
*/
(function(){
  if (window.__audioMasterStripModuleV1) return;
  window.__audioMasterStripModuleV1 = true;

  var masterState = {
    volume: 80,    // same 0..100 scale as current vfader strips
    muted: false,
    level: 0
  };

  try {
    var mv = parseFloat(localStorage.getItem('coproducer_master_volume_v1') || '80');
    if (Number.isFinite(mv)) masterState.volume = Math.max(0, Math.min(100, mv));
  } catch(_) {}

  try {
    masterState.muted = localStorage.getItem('coproducer_master_muted_v1') === '1';
  } catch(_) {}

  function saveMasterState(){
    try { localStorage.setItem('coproducer_master_volume_v1', String(masterState.volume)); } catch(_){}
    try { localStorage.setItem('coproducer_master_muted_v1', masterState.muted ? '1' : '0'); } catch(_){}
  }

  function clamp(v, min, max){
    v = Number(v);
    if (!Number.isFinite(v)) v = min;
    if (v < min) v = min;
    if (v > max) v = max;
    return v;
  }

  function ensureCss(){
    if (document.getElementById('__audioMasterStripCssV1')) return;

    var st = document.createElement('style');
    st.id = '__audioMasterStripCssV1';
    st.textContent = [
      '.mixerWrap{overflow-x:auto;overflow-y:hidden;}',
      '#stripRow{display:flex !important;flex-wrap:nowrap !important;align-items:stretch !important;gap:8px !important;}',
      '#stripRow>.strip{flex:1 1 0 !important;min-width:0 !important;width:auto !important;}',
      '#stripRow>.strip[data-master-strip="1"]{flex:1 1 0 !important;min-width:0 !important;width:auto !important;}',
      '#stripRow>.strip[data-master-strip="1"] .stripTop b{color:#ffd089 !important;}',
      '#stripRow>.strip[data-master-strip="1"] .state{color:#ffd089 !important;opacity:.92;}',
      '#stripRow>.strip[data-master-strip="1"] .faderCap{box-shadow:inset 0 0 0 1px rgba(208,138,47,.60),0 0 12px rgba(208,138,47,.18) !important;}',
      '#stripRow>.strip[data-master-strip="1"] .vuFill{filter:saturate(1.12) brightness(1.04);}',
      '#stripRow>.strip[data-master-strip="1"] .volLbl{color:#ffd089 !important;}'
    ].join('\n');

    document.head.appendChild(st);
  }

  function getStripRow(){
    return document.getElementById('stripRow');
  }

  function getMasterStrip(){
    var row = getStripRow();
    return row ? row.querySelector('.strip[data-master-strip="1"]') : null;
  }

  function getMediaStrip(){
    var row = getStripRow();
    if (!row) return null;
    var strips = row.querySelectorAll('.strip');
    if (!strips || !strips.length) return null;
    return strips[strips.length - 1] || null;
  }

  function removeLegacyMasterWidgets(){
    document.querySelectorAll('[data-ch="master"], .mixerStrip--master, .ch[data-ch="master"]').forEach(function(el){
      if (el.closest && el.closest('#stripRow') && el.classList.contains('strip')) return;
      try { el.remove(); } catch(_){}
    });
  }

  function capTopFromValue(v){
    var value = clamp(v, 0, 100);
    var maxTravel = 118;
    return Math.round((100 - value) / 100 * maxTravel);
  }

  function computeLevelFromModel(){
    var sum = 0;
    var count = 0;

    try {
      if (typeof slots !== 'undefined' && Array.isArray(slots)) {
        for (var i = 0; i < slots.length; i++) {
          var s = slots[i];
          if (!s) continue;
          var hear = (s.micMonitorOn !== false);
          var lvl = Number(s._meterLevel || s.meter || s.level || 0) || 0;
          if (hear) {
            sum += lvl;
            count++;
          }
        }
      }
    } catch(_) {}

    try {
      if (typeof mediaState !== 'undefined' && mediaState) {
        var mediaLvl = Number(mediaState._meterLevel || mediaState.meter || mediaState.level || 0) || 0;
        var mediaAudible = !mediaState.muted;
        if (mediaAudible) {
          sum += mediaLvl;
          count++;
        }
      }
    } catch(_) {}

    var avg = count > 0 ? (sum / count) : 0;
    avg = clamp(avg, 0, 1);
    var volScale = clamp(masterState.volume / 100, 0, 1);
    masterState.level = masterState.muted ? 0 : clamp(avg * volScale, 0, 1);
    return masterState.level;
  }

  function computeLevelFromVisibleStrips(){
    var row = getStripRow();
    if (!row) return 0;

    var strips = row.querySelectorAll('.strip:not([data-master-strip="1"])');
    if (!strips.length) return 0;

    var sum = 0;
    var count = 0;

    strips.forEach(function(strip){
      var vuL = strip.querySelector('.vuFill[id$="-L"], .vuCol:nth-child(1) .vuFill');
      var vuR = strip.querySelector('.vuFill[id$="-R"], .vuCol:nth-child(2) .vuFill');

      var l = 0, r = 0;

      try {
        l = parseFloat((vuL && vuL.style && vuL.style.height || '0').replace('%','')) || 0;
        r = parseFloat((vuR && vuR.style && vuR.style.height || '0').replace('%','')) || 0;
      } catch(_) {}

      var avg = (l + r) / 2 / 100;
      if (avg > 0) {
        sum += avg;
        count++;
      }
    });

    var out = count > 0 ? (sum / count) : 0;
    out = clamp(out, 0, 1);
    var volScale = clamp(masterState.volume / 100, 0, 1);
    masterState.level = masterState.muted ? 0 : clamp(out * volScale, 0, 1);
    return masterState.level;
  }

  function computeMasterLevel(){
    var level = computeLevelFromModel();
    if (!(level > 0)) level = computeLevelFromVisibleStrips();
    masterState.level = clamp(level, 0, 1);
    return masterState.level;
  }

  function buildMasterStrip(){
    var media = getMediaStrip();
    if (!media) return null;

    var clone = media.cloneNode(true);
    clone.id = 'st-master';
    clone.setAttribute('data-master-strip', '1');

    clone.querySelectorAll('[id]').forEach(function(el){
      if (el.classList.contains('state')) el.id = 'st-master-state';
      else if (el.classList.contains('vfader')) el.id = 'f-master';
      else if (el.classList.contains('faderCap')) el.id = 'cap-master';
      else if (el.classList.contains('vuFill')) {
        if (!el.id || /-L$/.test(el.id)) el.id = 'vu-master-L';
        else if (!el.id || /-R$/.test(el.id)) el.id = 'vu-master-R';
        else el.removeAttribute('id');
      } else {
        el.removeAttribute('id');
      }
    });

    var title = clone.querySelector('.stripTop b');
    if (title) title.textContent = 'MASTER';

    var state = clone.querySelector('.state');
    if (state) {
      state.textContent = masterState.muted ? 'MUTED' : 'BUS';
      state.title = 'Double-click to mute/unmute Master';
      state.style.cursor = 'pointer';
      state.setAttribute('data-master-mute-toggle', '1');
    }

    var fader = clone.querySelector('.vfader');
    if (fader) {
      fader.value = String(masterState.volume);
      fader.setAttribute('data-master-fader', '1');
    }

    var cap = clone.querySelector('.faderCap');
    if (cap) cap.style.top = capTopFromValue(masterState.volume) + 'px';

    var vuL = clone.querySelector('#vu-master-L');
    var vuR = clone.querySelector('#vu-master-R');
    if (vuL) vuL.style.height = '0%';
    if (vuR) vuR.style.height = '0%';

    return clone;
  }

  function ensureSingleMasterStrip(){
    ensureCss();
    removeLegacyMasterWidgets();

    var row = getStripRow();
    if (!row) return null;

    var masters = row.querySelectorAll('.strip[data-master-strip="1"], .strip#st-master');
    if (masters.length > 1) {
      for (var i = 1; i < masters.length; i++) {
        try { masters[i].remove(); } catch(_){}
      }
    }

    var existing = getMasterStrip();
    if (existing) return existing;

    var master = buildMasterStrip();
    if (!master) return null;

    row.appendChild(master);
    return master;
  }

  function refreshMasterStrip(){
    var strip = ensureSingleMasterStrip();
    if (!strip) return;

    computeMasterLevel();

    var state = strip.querySelector('.state');
    if (state) state.textContent = masterState.muted ? 'MUTED' : 'BUS';

    var fader = strip.querySelector('.vfader');
    if (fader) fader.value = String(masterState.volume);

    var cap = strip.querySelector('.faderCap');
    if (cap) cap.style.top = capTopFromValue(masterState.volume) + 'px';

    var h = Math.round(masterState.level * 100);
    var vuL = strip.querySelector('#vu-master-L');
    var vuR = strip.querySelector('#vu-master-R');
    if (vuL) vuL.style.height = h + '%';
    if (vuR) vuR.style.height = h + '%';
  }

  function bindEvents(){
    document.addEventListener('input', function(ev){
      var el = ev.target;
      if (!el || !el.matches || !el.matches('[data-master-fader="1"], #f-master')) return;
      masterState.volume = clamp(el.value, 0, 100);
      saveMasterState();
      refreshMasterStrip();
    }, true);

    document.addEventListener('dblclick', function(ev){
      var toggle = ev.target && ev.target.closest ? ev.target.closest('[data-master-mute-toggle="1"]') : null;
      if (!toggle) return;
      ev.preventDefault();
      masterState.muted = !masterState.muted;
      saveMasterState();
      refreshMasterStrip();
    }, true);
  }

  function hookRender(){
    try {
      if (typeof window.renderUI === 'function' && !window.renderUI.__audioMasterWrapped) {
        var orig = window.renderUI;
        var wrapped = function(){
          var out = orig.apply(this, arguments);
          setTimeout(refreshMasterStrip, 0);
          return out;
        };
        wrapped.__audioMasterWrapped = true;
        window.renderUI = wrapped;
      }
    } catch(_) {}

    try {
      var tries = 0;
      var t = setInterval(function(){
        var row = getStripRow();
        if (row && !row.__audioMasterObserverBound) {
          row.__audioMasterObserverBound = true;
          var mo = new MutationObserver(function(){
            setTimeout(refreshMasterStrip, 0);
          });
          mo.observe(row, { childList:true, subtree:false });
        }
        tries++;
        if (tries > 40 || row) clearInterval(t);
      }, 250);
    } catch(_) {}
  }

  function boot(){
    ensureSingleMasterStrip();
    refreshMasterStrip();
    bindEvents();
    hookRender();
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', boot, { once:true });
  } else {
    boot();
  }
})();
JS

# Inject script tag after stream.module.js if not already present
if ! grep -q 'assets/js/modules/audio_master_strip.js' "$PHPF"; then
  awk '
  {
    print
    if ($0 ~ /assets\/js\/modules\/stream\.module\.js/) {
      print "<script src=\"assets/js/modules/audio_master_strip.js\"></script>"
    }
  }' "$PHPF" > "${PHPF}.tmp_audio_master"
  mv "${PHPF}.tmp_audio_master" "$PHPF"
fi

echo "Created:"
echo "  $JSF"
echo
echo "Backup:"
echo "  ${PHPF}.bak_audio_master_${STAMP}"
echo
echo "Verification:"
php -l "$PHPF"
grep -n 'audio_master_strip.js' "$PHPF" || true
echo
echo "Module head:"
sed -n '1,40p' "$JSF"
