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

if [ "$#" -lt 1 ]; then
  echo "Usage: $0 /path/to/studio/public"
  echo "Example: $0 /home/itahukamedia/public_html/studio.itahukamedia.com/public"
  exit 1
fi

ROOT="$1"
JS="$ROOT/assets/js/modules/coproducer.inline-main.js"
JOIN="$ROOT/join.php"

for f in "$JS" "$JOIN"; do
  if [ ! -f "$f" ]; then
    echo "Missing file: $f" >&2
    exit 1
  fi
done

if ! command -v php >/dev/null 2>&1; then
  echo "ERROR: php CLI not found in PATH." >&2
  exit 1
fi

STAMP="$(date +%Y%m%d_%H%M%S)"
cp -a "$JS" "$JS.bak.$STAMP"
cp -a "$JOIN" "$JOIN.bak.$STAMP"
echo "Backups created:"
echo " - $JS.bak.$STAMP"
echo " - $JOIN.bak.$STAMP"

php <<'PHP' "$JS" "$JOIN"
<?php
$jsPath = $argv[1];
$joinPath = $argv[2];

function fail($msg){ fwrite(STDERR, $msg . PHP_EOL); exit(1); }
function read_strict($p){ $c = file_get_contents($p); if ($c === false) fail("Cannot read: $p"); return $c; }
function write_strict($p, $c){ if (file_put_contents($p, $c) === false) fail("Cannot write: $p"); }
function patch_once(&$text, $search, $replace, $label){
  if (strpos($text, $replace) !== false) { echo "Already patched: $label\n"; return; }
  $count = substr_count($text, $search);
  if ($count !== 1) fail("Patch failed for $label: expected 1 exact match, got $count");
  $text = str_replace($search, $replace, $text);
  echo "Patched: $label\n";
}

$js = read_strict($jsPath);
$join = read_strict($joinPath);

/* ================================
   coproducer.inline-main.js
   1) Render real guest name instead of G1/G2...
   ================================ */
patch_once(
  $js,
  <<<'TXT'
    const info = document.createElement("div");
    const name = `G${s.idx+1}`;
TXT,
  <<<'TXT'
    const info = document.createElement("div");
    const name = String((s && s.name) ? s.name : `G${s.idx+1}`);
TXT,
  'renderUI guest name uses slot.name'
);

/* 2) Seed existing participant name into slot */
patch_once(
  $js,
  <<<'TXT'
      const s = findSlotByUid(uid) || allocateSlotForUser({ uid });
      if (!s) return;

      const vTrack = getParticipantVideoTrack(participant);
TXT,
  <<<'TXT'
      const s = findSlotByUid(uid) || allocateSlotForUser({ uid, name: (participant?.name || participant?.identity || uid) });
      if (!s) return;
      if (!s.name) s.name = String(participant?.name || participant?.identity || uid);

      const vTrack = getParticipantVideoTrack(participant);
TXT,
  'seed existing participant name'
);

/* 3) TrackSubscribed path also stores real participant name */
patch_once(
  $js,
  <<<'TXT'
      const s = findSlotByUid(uid) || allocateSlotForUser({ uid });
      if (!s) return;

      if (track.kind === "video"){
TXT,
  <<<'TXT'
      const s = findSlotByUid(uid) || allocateSlotForUser({ uid, name: (participant?.name || participant?.identity || uid) });
      if (!s) return;
      if (!s.name) s.name = String(participant?.name || participant?.identity || uid);

      if (track.kind === "video"){
TXT,
  'TrackSubscribed stores real participant name'
);

/* ================================
   join.php
   4) Prompt BOTH cam+mic permissions at Join click before connecting
   ================================ */
patch_once(
  $join,
  <<<'TXT'
  async function fetchToken({roomName, name, publish, subscribe}){
TXT,
  <<<'TXT'
  async function promptJoinDevices(){
    try{
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) return;
      const stream = await navigator.mediaDevices.getUserMedia({ audio:true, video:true });
      try{
        for (const t of (stream.getTracks() || [])) {
          try{ t.stop(); }catch(_){}
        }
      }catch(_){}
    }catch(err){
      console.warn("Join device prompt failed:", err);
      throw err;
    }
  }

  async function fetchToken({roomName, name, publish, subscribe}){
TXT,
  'add promptJoinDevices helper'
);

/* 5) Run permission prompt before token/connect */
patch_once(
  $join,
  <<<'TXT'
      const token = await fetchToken({ roomName, name, publish: true, subscribe: true });

      await lkRoom.connect(lkUrl, token);
TXT,
  <<<'TXT'
      await promptJoinDevices();
      const token = await fetchToken({ roomName, name, publish: true, subscribe: true });

      await lkRoom.connect(lkUrl, token);
TXT,
  'prompt devices before connect'
);

/* 6) Auto-publish both cam and mic after connect */
patch_once(
  $join,
  <<<'TXT'
    autoPublishCam: true,
    autoPublishMic: false,
TXT,
  <<<'TXT'
    autoPublishCam: true,
    autoPublishMic: true,
TXT,
  'enable auto mic publish'
);

/* ================================
   7) Remove studio-return from join guest strip
   ================================ */
patch_once(
  $join,
  <<<'TXT'
    for (const it of participants){
      const p = it.p;
      const key = it.key;
      const name = bestDisplayName(p, it.isLocal ? ((els.name && els.name.value.trim()) || "Me") : "Guest");
TXT,
  <<<'TXT'
    for (const it of participants){
      const p = it.p;
      const key = it.key;
      if (!it.isLocal && String((p && p.identity) || "").trim() === "studio-return") continue;
      const name = bestDisplayName(p, it.isLocal ? ((els.name && els.name.value.trim()) || "Me") : "Guest");
TXT,
  'exclude studio-return from join guest strip'
);

/* ================================
   8) Force remote stage label + selector to studio-return
   ================================ */
patch_once(
  $join,
  <<<'TXT'
  function pickRemoteVideoParticipant(){
    if (!lkRoom) return null;
    const remotes = Array.from(lkRoom.remoteParticipants.values());
    for (const p of remotes){
      for (const pub of p.videoTrackPublications.values()){
        if (pub.track) return p;
      }
    }
    for (const p of remotes){
      if (p.videoTrackPublications.size > 0) return p;
    }
    return remotes[0] || null;
  }
TXT,
  <<<'TXT'
  function pickRemoteVideoParticipant(){
    if (!lkRoom) return null;
    const remotes = Array.from(lkRoom.remoteParticipants.values());
    const studioReturn = remotes.find(p => String((p && p.identity) || "").trim() === "studio-return");
    if (studioReturn) return studioReturn;
    for (const p of remotes){
      for (const pub of p.videoTrackPublications.values()){
        if (pub.track) return p;
      }
    }
    for (const p of remotes){
      if (p.videoTrackPublications.size > 0) return p;
    }
    return remotes[0] || null;
  }
TXT,
  'prefer studio-return participant'
);

patch_once(
  $join,
  <<<'TXT'
    const who = bestDisplayName(p, "Remote");
TXT,
  <<<'TXT'
    const who = (String((p && p.identity) || "").trim() === "studio-return")
      ? "Remote: studio-return"
      : bestDisplayName(p, "Remote");
TXT,
  'stable remote label'
);

write_strict($jsPath, $js);
write_strict($joinPath, $join);
echo "Done:\n - $jsPath\n - $joinPath\n";
PHP

echo
echo "Patch complete."
echo
echo "Syntax check:"
echo "php -l \"$JOIN\""
echo
echo "Then hard-refresh BOTH pages with cache disabled."
echo
echo "Expected:"
echo " - coproducer Guest List shows typed guest name"
echo " - Join prompts for cam+mic on Join click"
echo " - guest publishes both AV immediately after connect"
echo " - studio-return disappears from join guest strip and remains only as Remote: studio-return"
