<?php
require_once __DIR__ . '/../includes/conn.php';

include '../includes/header.php';

// Optional: if you have functions.php with requireRole() uncomment next line
// include_once __DIR__ . '/../includes/functions.php'; requireRole('admin');

$admin_name = $_SESSION['first_name'];
?>
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Proctoring Dashboard</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <!-- Icons -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">

  <style>
    body {
      background-color: #f8f9fa;
      font-family: "Poppins", sans-serif;
    }
    .navbar {
      background: linear-gradient(45deg, #0d6efd, #007bff);
    }
    .navbar-brand {
      font-weight: 600;
      color: #fff !important;
    }
    .student-card {
      border: none;
      border-radius: 10px;
      box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
      transition: transform 0.2s;
    }
    .student-card:hover {
      transform: translateY(-4px);
    }
    video {
      width: 100%;
      height: 220px;
      border-radius: 8px;
      background: #000;
    }
    .status-dot {
      height: 10px;
      width: 10px;
      border-radius: 50%;
      display: inline-block;
      margin-right: 6px;
    }
    .status-online {
      background-color: #28a745;
    }
    .status-offline {
      background-color: #dc3545;
    }
    .meta-line { font-size: 0.9rem; color: #6c757d; }
  </style>
</head>
<body>

<!-- Top Navbar -->
<nav class="navbar navbar-expand-lg navbar-dark">
  <div class="container-fluid">
    <a class="navbar-brand" href="#"><i class="bi bi-eye-fill me-2"></i>Exam Monitoring Dashboard</a>
    <div class="d-flex align-items-center text-white">
      <i class="bi bi-person-circle me-2"></i><?php echo htmlspecialchars($admin_name); ?>
    </div>
  </div>
</nav>

<!-- Main Content -->
<div class="container my-4">
  <div class="d-flex justify-content-between align-items-center mb-3">
    <h4 class="fw-semibold"><i class="bi bi-camera-video me-2 text-primary"></i>Active Students</h4>
    <div>
      <span class="badge bg-secondary" id="totalCount">0 seen</span>
      <span class="badge bg-success" id="onlineCount">0 online</span>
    </div>
  </div>

  <div id="studentsGrid" class="row g-4"></div>
</div>

<!-- Socket.IO -->
<script src="https://cdn.socket.io/4.8.0/socket.io.min.js"></script>
<script>
(() => {
  const SIGNALING_URL = 'http://localhost:3000'; // change to server IP if needed
  const socket = io(SIGNALING_URL, { transports: ['websocket'] });

  const studentsGrid = document.getElementById('studentsGrid');
  const totalCountEl = document.getElementById('totalCount');
  const onlineCountEl = document.getElementById('onlineCount');

  // pcs: studentId -> { pc, info, connected (bool) }
  const pcs = {};

  socket.on('connect', () => {
    console.log('Connected to signaling server as admin', socket.id);
    socket.emit('role', 'admin', { adminId: socket.id, name: '<?php echo addslashes($admin_name); ?>' });
  });

  socket.on('student-joined', ({ studentId, info }) => {
    console.log('student-joined', studentId, info);
    addStudentCard(studentId, info);
    refreshCounts();
  });

  socket.on('student-left', ({ studentId }) => {
    console.log('student-left', studentId);
    removeStudentCard(studentId);
    refreshCounts();
  });

  // Offer from student -> create peer and answer
  socket.on('offer', async ({ studentId, sdp, info }) => {
    console.log('Received offer from', studentId, info);

    // Ensure card exists before attaching streams
    addStudentCard(studentId, info);

    // If existing pc, close and recreate
    if (pcs[studentId] && pcs[studentId].pc) {
      try { pcs[studentId].pc.close(); } catch(e) {}
      delete pcs[studentId];
    }

    const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
    pcs[studentId] = { pc, info, connected: false };

    // Prepare or find the video element
    const videoEl = document.getElementById('video-' + studentId);
    const remoteStream = new MediaStream();
    if (videoEl) videoEl.srcObject = remoteStream;
    else console.warn('video element missing for', studentId);

    pc.ontrack = (ev) => {
      // Support both ev.streams and ev.track
      if (ev.streams && ev.streams.length) {
        ev.streams.forEach(s => s.getTracks().forEach(t => remoteStream.addTrack(t)));
      } else if (ev.track) {
        remoteStream.addTrack(ev.track);
      }
      // Mark connected when first track arrives
      if (!pcs[studentId].connected) {
        pcs[studentId].connected = true;
        setStatus(studentId, 'online');
        refreshCounts();
      }
      console.log('Track arrived for', studentId, ev);
    };

    pc.onicecandidate = event => {
      if (event.candidate) {
        socket.emit('ice-candidate', { to: studentId, candidate: event.candidate, from: socket.id });
      }
    };

    pc.onconnectionstatechange = () => {
      console.log('Connection state for', studentId, pc.connectionState);
      if (pc.connectionState === 'failed' || pc.connectionState === 'disconnected' || pc.connectionState === 'closed') {
        pcs[studentId].connected = false;
        setStatus(studentId, 'offline');
        refreshCounts();
      }
    };

    try {
      await pc.setRemoteDescription(new RTCSessionDescription(sdp));
      const answer = await pc.createAnswer();
      await pc.setLocalDescription(answer);
      socket.emit('answer', { studentId, sdp: pc.localDescription });
      console.log('Sent answer to', studentId);
    } catch (err) {
      console.error('Error handling offer for', studentId, err);
      setStatus(studentId, 'offline');
    }
  });

  socket.on('ice-candidate', async ({ candidate, from }) => {
    const entry = pcs[from];
    if (entry && entry.pc) {
      try {
        await entry.pc.addIceCandidate(candidate);
      } catch (e) {
        console.warn('addIceCandidate failed for', from, e);
      }
    } else {
      console.warn('ICE candidate for unknown peer', from);
    }
  });

  // UI helpers
  function addStudentCard(studentId, info = {}) {
    if (document.getElementById('card-' + studentId)) {
      // if card exists, update name if needed
      const nameEl = document.querySelector('#card-' + studentId + ' .student-name');
      if (nameEl && info.name) nameEl.textContent = info.name;
      return;
    }

    const card = document.createElement('div');
    card.className = 'col-md-4';
    card.id = 'card-' + studentId;
    card.innerHTML = `
      <div class="card student-card">
        <div class="card-body">
          <div class="d-flex justify-content-between align-items-center mb-2">
            <h6 class="mb-0 student-name"><i class="bi bi-person-fill text-primary me-2"></i>${escapeHtml(info.name || 'Unknown')}</h6>
            <span id="status-${studentId}" class="status-dot status-offline"></span>
          </div>
          <div class="meta-line mb-2"><small>ID: ${escapeHtml(studentId)}</small></div>
          <video id="video-${studentId}" autoplay playsinline muted></video>
      </div>
    `;
    studentsGrid.appendChild(card);
    refreshCounts();
  }

  function removeStudentCard(studentId) {
    const card = document.getElementById('card-' + studentId);
    if (card) card.remove();
    if (pcs[studentId]) {
      try { pcs[studentId].pc.close(); } catch (e) {}
      delete pcs[studentId];
    }
    refreshCounts();
  }

  function disconnectStudent(studentId) {
    // optionally tell the student to stop (not implemented server-side)
    removeStudentCard(studentId);
  }

  function requestSnapshot(studentId) {
    // placeholder: in future you can use a datachannel to request a snapshot
    alert('Snapshot request would be sent to: ' + studentId);
  }

  function setStatus(studentId, state) {
    const dot = document.getElementById('status-' + studentId);
    if (!dot) return;
    dot.classList.remove('status-online', 'status-offline');
    dot.classList.add(state === 'online' ? 'status-online' : 'status-offline');
  }

  function refreshCounts() {
    const total = document.querySelectorAll('#studentsGrid > .col-md-4').length;
    const online = Object.values(pcs).filter(p => p.connected).length;
    totalCountEl.textContent = `${total} seen`;
    onlineCountEl.textContent = `${online} online`;
  }

  function escapeHtml(s) {
    if (!s) return '';
    return s.replace(/[&<>"']/g, (m) => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[m]);
  }

  // expose a couple of functions to window for debugging if necessary
  window.requestSnapshot = requestSnapshot;
  window.disconnectStudent = disconnectStudent;
  window.__pcs = pcs;

})();
</script>
</body>
</html>
