<?php
require_once 'includes/config.php';
requireLogin();
$uid = $_SESSION['user_id'];

$UPLOAD_DIR = __DIR__ . '/assets/uploads/voice_notes/';
$UPLOAD_REL = 'assets/uploads/voice_notes/';
if (!is_dir($UPLOAD_DIR)) mkdir($UPLOAD_DIR, 0755, true);

// ── AJAX actions ─────────────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
    $action = $_POST['action'] ?? '';

    if ($action === 'upload_voice') {
        if (!isset($_FILES['audio']) || $_FILES['audio']['error'] !== 0) {
            jsonResponse(['success' => false, 'message' => 'Recording upload failed. Please try again.']);
        }
        $file = $_FILES['audio'];
        $maxSize = 15 * 1024 * 1024; // 15MB cap per recording
        if ($file['size'] > $maxSize) jsonResponse(['success' => false, 'message' => 'Recording too large (max 15MB).']);

        $title   = sanitize($_POST['title'] ?? '') ?: 'Voice Note';
        $subId   = (int)($_POST['subject_id'] ?? 0) ?: null;
        $dur     = (int)($_POST['duration'] ?? 0);

        // Verify subject belongs to user
        if ($subId) {
            $chk = $pdo->prepare("SELECT id FROM subjects WHERE id=? AND user_id=?");
            $chk->execute([$subId, $uid]);
            if (!$chk->fetch()) $subId = null;
        }

        // Determine the real file extension from what the browser actually recorded
        // (previously this was hardcoded to .webm, which broke playback whenever a
        // device — e.g. iPhone/iOS Safari — actually recorded mp4/aac audio instead).
        $clientMime = $_POST['mime_type'] ?? '';
        if (stripos($clientMime, 'mp4') !== false) {
            $ext = 'm4a';
        } elseif (stripos($clientMime, 'ogg') !== false) {
            $ext = 'ogg';
        } else {
            $ext = 'webm';
        }
        $name = 'voice_' . $uid . '_' . time() . '_' . bin2hex(random_bytes(4)) . '.' . $ext;
        $dest = $UPLOAD_DIR . $name;
        if (move_uploaded_file($file['tmp_name'], $dest)) {
            $rel = $UPLOAD_REL . $name;
            $pdo->prepare("INSERT INTO voice_notes (user_id,subject_id,title,file_path,duration_seconds,file_size) VALUES (?,?,?,?,?,?)")
                ->execute([$uid, $subId, $title, $rel, $dur, $file['size']]);
            jsonResponse(['success' => true, 'message' => 'Voice note saved!', 'id' => $pdo->lastInsertId()]);
        } else {
            jsonResponse(['success' => false, 'message' => 'Could not save recording on server.']);
        }
    }

    if ($action === 'rename_voice') {
        $id = (int)($_POST['id'] ?? 0);
        $title = sanitize($_POST['title'] ?? '');
        if (!$title) jsonResponse(['success' => false, 'message' => 'Title cannot be empty.']);
        $pdo->prepare("UPDATE voice_notes SET title=? WHERE id=? AND user_id=?")->execute([$title, $id, $uid]);
        jsonResponse(['success' => true]);
    }

    if ($action === 'delete_voice') {
        $id = (int)($_POST['id'] ?? 0);
        $stmt = $pdo->prepare("SELECT file_path FROM voice_notes WHERE id=? AND user_id=?");
        $stmt->execute([$id, $uid]);
        $path = $stmt->fetchColumn();
        if ($path) {
            $pdo->prepare("DELETE FROM voice_notes WHERE id=? AND user_id=?")->execute([$id, $uid]);
            $abs = __DIR__ . '/' . $path;
            if (file_exists($abs)) @unlink($abs);
        }
        jsonResponse(['success' => true]);
    }

    jsonResponse(['success' => false, 'message' => 'Unknown action.']);
}

// ── Page data ─────────────────────────────────────────────────────────
$subjects = $pdo->prepare("SELECT id,name,color FROM subjects WHERE user_id=? ORDER BY name");
$subjects->execute([$uid]);
$subjects = $subjects->fetchAll();

$notesQ = $pdo->prepare("
    SELECT vn.*, s.name AS subject_name, s.color AS subject_color
    FROM voice_notes vn
    LEFT JOIN subjects s ON s.id = vn.subject_id
    WHERE vn.user_id = ?
    ORDER BY vn.created_at DESC
");
$notesQ->execute([$uid]);
$voiceNotes = $notesQ->fetchAll();

$totalSize = array_sum(array_column($voiceNotes, 'file_size'));

require_once 'includes/header.php';
renderHeader('Voice Notes', 'voice-notes');
?>

<style>
.vn-wrap { max-width: 760px; }

/* ── Header ── */
.vn-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 22px; flex-wrap: wrap; }
.vn-title { font-size: 22px; font-weight: 800; font-family: 'Sora', sans-serif; color: var(--text-primary); display: flex; align-items: center; gap: 9px; }
.vn-subtitle { font-size: 13px; color: var(--text-muted); margin-top: 4px; line-height: 1.5; }
.vn-stat-pill {
    font-size: 12px; font-weight: 700; color: var(--text-secondary); background: var(--bg-secondary);
    border: 1px solid var(--border); border-radius: 99px; padding: 7px 14px; white-space: nowrap;
}
.vn-stat-pill b { color: var(--accent); font-weight: 800; }

/* ── Recorder ── */
.vn-recorder {
    background: linear-gradient(160deg, var(--bg-card) 0%, var(--bg-secondary) 100%);
    border: 1px solid var(--border); border-radius: 20px; padding: 28px 24px; margin-bottom: 22px;
    position: relative; overflow: hidden;
}
.vn-recorder::before {
    content: ''; position: absolute; top: -80px; left: -80px; width: 240px; height: 240px;
    background: radial-gradient(circle, rgba(99,102,241,.10) 0%, transparent 70%);
    border-radius: 50%; pointer-events: none;
}
.vn-rec-row { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; position: relative; z-index: 1; }

/* Mic button + pulse ring */
.vn-mic-wrap { position: relative; width: 76px; height: 76px; flex-shrink: 0; }
.vn-pulse {
    position: absolute; inset: 0; border-radius: 50%; background: rgba(239,68,68,.35);
    opacity: 0; transform: scale(1);
}
.vn-mic-wrap.recording .vn-pulse { animation: vnPulse 1.6s ease-out infinite; }
@keyframes vnPulse {
    0%   { opacity: .55; transform: scale(1); }
    100% { opacity: 0;   transform: scale(1.7); }
}
.vn-mic {
    position: relative; width: 76px; height: 76px; border-radius: 50%; border: none;
    background: var(--gradient); color: #fff; font-size: 28px; cursor: pointer;
    box-shadow: 0 4px 18px rgba(99,102,241,.4); transition: transform .15s, background .2s; z-index: 1;
}
.vn-mic:hover { transform: scale(1.05); }
.vn-mic.recording { background: #ef4444; box-shadow: 0 4px 18px rgba(239,68,68,.45); }

.vn-rec-info { flex: 1; min-width: 220px; }
.vn-rec-status { font-size: 14px; font-weight: 700; color: var(--text-primary); margin-bottom: 8px; }

/* Live waveform — the signature element: reacts to actual mic input level */
.vn-waveform { display: none; align-items: center; gap: 3px; height: 34px; margin-bottom: 4px; }
.vn-waveform.active { display: flex; }
.vn-bar { width: 3px; min-height: 4px; border-radius: 2px; background: linear-gradient(180deg, #818cf8, #6366f1); transition: height .09s ease-out; }

.vn-timer { font-size: 24px; font-weight: 800; font-family: 'Courier New', monospace; color: var(--accent); display: none; letter-spacing: .5px; }
.vn-preview { width: 100%; margin-top: 10px; display: none; accent-color: var(--accent); }

.vn-save-row { display: none; margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--border); position: relative; z-index: 1; }
.vn-save-fields { display: flex; gap: 10px; flex-wrap: wrap; }
.vn-save-fields .form-input { min-width: 160px; }
.vn-save-fields input[type="text"] { flex: 2; }
.vn-save-fields select { flex: 1; }
.vn-save-actions { display: flex; gap: 8px; margin-top: 4px; }

/* ── Notes list ── */
.vn-list { display: flex; flex-direction: column; gap: 10px; }
.vn-note {
    background: var(--bg-card); border: 1px solid var(--border); border-left: 3px solid var(--note-color, var(--accent));
    border-radius: 14px; padding: 14px 16px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    transition: border-color .15s;
}
.vn-note:hover { border-color: var(--accent); }
.vn-note-main { flex: 1; min-width: 190px; }
.vn-note-title-row { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
.vn-note-title { font-size: 14.5px; font-weight: 700; color: var(--text-primary); }
.vn-icon-btn {
    width: 26px; height: 26px; border-radius: 7px; border: 1px solid transparent; background: transparent;
    color: var(--text-muted); font-size: 12px; cursor: pointer; display: inline-flex; align-items: center;
    justify-content: center; transition: all .15s; flex-shrink: 0;
}
.vn-icon-btn:hover { background: var(--bg-secondary); border-color: var(--border); color: var(--text-primary); }
.vn-icon-btn.danger:hover { color: #ef4444; border-color: rgba(239,68,68,.3); background: rgba(239,68,68,.08); }
.vn-note-meta { font-size: 11.5px; color: var(--text-muted); display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.vn-note-meta .badge { font-size: 10.5px; }
.vn-note-audio { max-width: 260px; flex: 1; min-width: 200px; height: 36px; }
.vn-note-actions { display: flex; gap: 6px; }

.vn-msg { font-size: 12.5px; font-weight: 600; padding: 8px 12px; border-radius: 8px; }
</style>

<div class="vn-wrap">

  <div class="vn-head">
    <div>
      <div class="vn-title">🎙️ Voice Notes</div>
      <div class="vn-subtitle">Record quick voice notes for any subject — great for revising on the go</div>
    </div>
    <div class="vn-stat-pill"><b><?= count($voiceNotes) ?></b> notes · <b><?= number_format($totalSize/1024/1024, 1) ?>MB</b> used</div>
  </div>

  <!-- Recorder -->
  <div class="vn-recorder">
    <div class="vn-rec-row">
      <div class="vn-mic-wrap" id="micWrap">
        <div class="vn-pulse"></div>
        <button id="recBtn" class="vn-mic" onclick="toggleRecording()">🎤</button>
      </div>
      <div class="vn-rec-info">
        <div id="recStatus" class="vn-rec-status">Tap the mic to start recording</div>
        <div id="waveform" class="vn-waveform">
          <?php for ($i = 0; $i < 28; $i++): ?><div class="vn-bar" style="height:4px"></div><?php endfor; ?>
        </div>
        <div id="recTimer" class="vn-timer">00:00</div>
        <audio id="recPreview" class="vn-preview" controls></audio>
      </div>
    </div>

    <div id="saveRow" class="vn-save-row">
      <div class="vn-save-fields">
        <input type="text" id="vTitle" class="form-input" placeholder="Title (e.g. Cell Division summary)">
        <select id="vSubject" class="form-input">
          <option value="">No subject</option>
          <?php foreach ($subjects as $s): ?>
            <option value="<?= $s['id'] ?>"><?= htmlspecialchars($s['name']) ?></option>
          <?php endforeach; ?>
        </select>
      </div>
      <div class="vn-save-actions">
        <button class="btn btn-primary" onclick="saveRecording()">💾 Save</button>
        <button class="btn btn-secondary" onclick="discardRecording()">Discard</button>
      </div>
      <div id="vMsg" class="vn-msg" style="display:none;margin-top:10px"></div>
    </div>
    <div id="micError" class="alert alert-error" style="display:none;margin-top:14px"></div>
  </div>

  <!-- Notes list -->
  <?php if (empty($voiceNotes)): ?>
    <div class="empty-state">
      <div class="empty-icon">🎙️</div>
      <h3>No voice notes yet</h3>
      <p>Record your first voice note above — perfect for quick explanations you want to hear back later.</p>
    </div>
  <?php else: ?>
    <div class="vn-list">
      <?php foreach ($voiceNotes as $n): ?>
        <div class="vn-note" id="vn-<?= $n['id'] ?>" style="--note-color: <?= htmlspecialchars($n['subject_color'] ?: '#6366f1') ?>">
          <div class="vn-note-main">
            <div class="vn-note-title-row">
              <span id="vn-title-<?= $n['id'] ?>" class="vn-note-title"><?= htmlspecialchars($n['title']) ?></span>
              <button class="vn-icon-btn" onclick="renameVoice(<?= $n['id'] ?>)" title="Rename">✏️</button>
            </div>
            <div class="vn-note-meta">
              <?php if ($n['subject_name']): ?><span class="badge badge-purple"><?= htmlspecialchars($n['subject_name']) ?></span><?php endif; ?>
              <span><?= date('M j, Y g:i A', strtotime($n['created_at'])) ?></span>
              <span>·</span>
              <span><?= number_format($n['file_size']/1024, 0) ?> KB</span>
            </div>
          </div>
          <audio class="vn-note-audio" controls src="<?= htmlspecialchars(SITE_URL . '/' . $n['file_path']) ?>"></audio>
          <div class="vn-note-actions">
            <a class="vn-icon-btn" href="<?= htmlspecialchars(SITE_URL . '/' . $n['file_path']) ?>" download title="Download">⬇️</a>
            <button class="vn-icon-btn danger" onclick="deleteVoice(<?= $n['id'] ?>)" title="Delete">🗑️</button>
          </div>
        </div>
      <?php endforeach; ?>
    </div>
  <?php endif; ?>

</div>

<script>
let mediaRecorder, chunks = [], recordedBlob = null, startTime, timerInterval, recMimeType = 'audio/webm';
let audioCtx, analyser, waveformRAF, waveformStream;
const waveBars = document.querySelectorAll('#waveform .vn-bar');

// Pick a mime type the CURRENT browser can actually record+play back.
// iOS Safari / many mobile browsers don't support webm at all — they
// only do mp4 (aac). Recording used to be hardcoded to 'audio/webm'
// regardless of what the device actually encoded, which produced a
// mismatched file (real bytes = mp4, but saved/served as .webm) that
// silently fails to play on those devices.
function pickSupportedMimeType() {
  const candidates = [
    'audio/mp4',
    'audio/mp4;codecs=mp4a.40.2',
    'audio/webm;codecs=opus',
    'audio/webm',
    'audio/ogg;codecs=opus'
  ];
  for (const c of candidates) {
    if (window.MediaRecorder && MediaRecorder.isTypeSupported && MediaRecorder.isTypeSupported(c)) {
      return c;
    }
  }
  return ''; // let the browser choose its own default
}

function startWaveform(stream) {
  try {
    audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    const source = audioCtx.createMediaStreamSource(stream);
    analyser = audioCtx.createAnalyser();
    analyser.fftSize = 64;
    source.connect(analyser);
    const data = new Uint8Array(analyser.frequencyBinCount);
    document.getElementById('waveform').classList.add('active');

    const draw = () => {
      analyser.getByteFrequencyData(data);
      waveBars.forEach((bar, i) => {
        const v = data[i % data.length] || 0;
        bar.style.height = Math.max(4, (v / 255) * 34) + 'px';
      });
      waveformRAF = requestAnimationFrame(draw);
    };
    draw();
  } catch (e) {
    // Visualization is a nice-to-have; recording still works without it.
  }
}

function stopWaveform() {
  if (waveformRAF) cancelAnimationFrame(waveformRAF);
  if (audioCtx) audioCtx.close().catch(() => {});
  document.getElementById('waveform').classList.remove('active');
  waveBars.forEach(bar => bar.style.height = '4px');
}

async function toggleRecording() {
  const btn = document.getElementById('recBtn');
  const micWrap = document.getElementById('micWrap');
  if (mediaRecorder && mediaRecorder.state === 'recording') {
    mediaRecorder.stop();
    return;
  }
  document.getElementById('micError').style.display = 'none';
  try {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    waveformStream = stream;
    chunks = [];
    const chosen = pickSupportedMimeType();
    mediaRecorder = chosen ? new MediaRecorder(stream, { mimeType: chosen }) : new MediaRecorder(stream);
    mediaRecorder.ondataavailable = e => chunks.push(e.data);
    mediaRecorder.onstop = () => {
      // Use whatever MediaRecorder actually produced, not a hardcoded guess.
      recMimeType = mediaRecorder.mimeType || chosen || 'audio/webm';
      recordedBlob = new Blob(chunks, { type: recMimeType });
      const url = URL.createObjectURL(recordedBlob);
      const preview = document.getElementById('recPreview');
      preview.src = url;
      preview.style.display = 'block';
      document.getElementById('saveRow').style.display = 'block';
      document.getElementById('recStatus').textContent = 'Recording complete — review & save below';
      document.getElementById('recTimer').style.display = 'none';
      btn.textContent = '🎤';
      btn.classList.remove('recording');
      micWrap.classList.remove('recording');
      clearInterval(timerInterval);
      stopWaveform();
      stream.getTracks().forEach(t => t.stop());
    };
    mediaRecorder.start();
    startWaveform(stream);
    startTime = Date.now();
    document.getElementById('recStatus').textContent = 'Recording… tap again to stop';
    document.getElementById('recTimer').style.display = 'block';
    btn.textContent = '⏹️';
    btn.classList.add('recording');
    micWrap.classList.add('recording');
    timerInterval = setInterval(() => {
      const s = Math.floor((Date.now() - startTime) / 1000);
      document.getElementById('recTimer').textContent =
        String(Math.floor(s/60)).padStart(2,'0') + ':' + String(s%60).padStart(2,'0');
    }, 250);
  } catch (err) {
    document.getElementById('micError').style.display = 'flex';
    document.getElementById('micError').textContent = '🚫 Microphone access denied or unavailable. Please allow mic permission and try again.';
  }
}

function discardRecording() {
  recordedBlob = null;
  document.getElementById('recPreview').style.display = 'none';
  document.getElementById('saveRow').style.display = 'none';
  document.getElementById('recStatus').textContent = 'Tap the mic to start recording';
  document.getElementById('vTitle').value = '';
}

function extFromMime(mime) {
  if (!mime) return 'webm';
  if (mime.includes('mp4')) return 'm4a';
  if (mime.includes('ogg')) return 'ogg';
  if (mime.includes('webm')) return 'webm';
  return 'webm';
}

async function saveRecording() {
  if (!recordedBlob) return;
  const duration = Math.round((Date.now() - startTime) / 1000);
  const fd = new FormData();
  fd.append('action', 'upload_voice');
  const ext = extFromMime(recMimeType);
  fd.append('audio', recordedBlob, 'note.' + ext);
  fd.append('mime_type', recMimeType);
  fd.append('title', document.getElementById('vTitle').value || 'Voice Note');
  fd.append('subject_id', document.getElementById('vSubject').value);
  fd.append('duration', duration);
  const msg = document.getElementById('vMsg');
  msg.style.display = 'block'; msg.className = 'vn-msg alert alert-info'; msg.textContent = 'Uploading…';
  const r = await fetch(location.href, { method:'POST', headers:{'X-Requested-With':'XMLHttpRequest'}, body: fd });
  const data = await r.json();
  if (data.success) { location.reload(); }
  else { msg.className = 'vn-msg alert alert-error'; msg.textContent = data.message || 'Upload failed.'; }
}

async function post(data) {
  const fd = new FormData();
  Object.entries(data).forEach(([k,v]) => fd.append(k, v));
  const r = await fetch(location.href, { method:'POST', headers:{'X-Requested-With':'XMLHttpRequest'}, body: fd });
  return r.json();
}

async function renameVoice(id) {
  const cur = document.getElementById('vn-title-' + id).textContent;
  const title = prompt('Rename voice note:', cur);
  if (title === null || !title.trim()) return;
  await post({ action:'rename_voice', id, title: title.trim() });
  document.getElementById('vn-title-' + id).textContent = title.trim();
}

async function deleteVoice(id) {
  if (!(await stConfirm('Delete this voice note? This cannot be undone.'))) return;
  await post({ action:'delete_voice', id });
  const el = document.getElementById('vn-' + id);
  if (el) el.remove();
}
</script>

<?php require_once 'includes/footer.php'; renderFooter(); ?>
