let qrScanner = null;
let qrBusy = false;
let currentRoutePoints = [];
let currentAttendanceRows = [];
let currentQrMode = 'checkin';
let selectedAttendanceUserIds = new Set();

function activeQrMode() {
  return document.querySelector('input[name="qrMode"]:checked')?.value || currentQrMode || 'checkin';
}

function pointLabel(type) {
  return ({
    start: 'Start',
    checkpoint: 'Checkpoint',
    station: 'Station',
    water_station: 'Water station',
    medical_station: 'Medical station',
    rest_station: 'Rest station',
    end: 'Finish'
  })[type || 'checkpoint'] || 'Checkpoint';
}

function updateQrModeUi() {
  currentQrMode = activeQrMode();
  document.querySelectorAll('.qr-mode-card').forEach(card => {
    const input = card.querySelector('input[name="qrMode"]');
    card.classList.toggle('active', input && input.value === currentQrMode);
  });
  const stationPanel = document.getElementById('stationPickerPanel');
  if (stationPanel) stationPanel.hidden = currentQrMode !== 'checkpoint';
  const submit = document.getElementById('manualQrSubmitBtn');
  if (submit) {
    submit.textContent = currentQrMode === 'finish' ? 'Finish by QR' : (currentQrMode === 'checkpoint' ? 'Record station QR' : 'Check-in by QR');
  }
  const msg = document.getElementById('qrMsg');
  if (msg && !msg.textContent) {
    msg.className = 'notice';
    msg.textContent = currentQrMode === 'finish'
      ? 'Finish mode active. Scan a member QR at the end of the walk.'
      : currentQrMode === 'checkpoint'
        ? 'Station mode active. Only stations marked as Requires QR check-in are shown here. Choose one, then scan the member QR.'
        : 'Check-in mode active. Scan a member QR to check them in.';
  }
}

async function loadWalkOptions(){
 let res=await Pyrk.get('walks.php',{action:'admin_all'});
 if(!res.ok) res=await Pyrk.get('walks.php');
 const select=document.getElementById('walkSelect');
 const now=new Date();
 const todayIso=`${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`;
 const walks=(res.data?.walks||[]).filter(w=>String(w.status||'').toLowerCase().trim()==='open'||String(w.walk_date||'')>=todayIso);
 select.innerHTML=walks.map(w=>`<option value="${w.id}">${Pyrk.esc(w.title)} - ${Pyrk.formatDate(w.walk_date)}</option>`).join('');
 const urlWalk=new URL(location.href).searchParams.get('walk_id'); if(urlWalk) select.value=urlWalk;
 loadAttendance();
}

function attendanceStatusLabel(a) {
 const status = String(a.status || a.registration_status || 'registered');
 if (status === 'partially_completed') return 'Partially completed';
 if (status === 'manual_verified') return 'Manually finished';
 if (status === 'checked_in') return 'Checked in';
 return status.replace(/_/g, ' ');
}

function isCompleted(a) {
 const status = String(a.status || '');
 return status === 'finished' || status === 'partially_completed' || status === 'manual_verified' || !!a.finish_time;
}

function isCheckedIn(a) {
 return !!a.check_in_time && !isCompleted(a);
}

function canBulkCheckIn(a) {
 return !isCompleted(a) && !isCheckedIn(a);
}

function attendanceUserId(a) {
 return Number(a.user_id || 0);
}

function selectionCheckboxHtml(a) {
 const userId = attendanceUserId(a);
 const eligible = canBulkCheckIn(a);
 const checked = selectedAttendanceUserIds.has(userId) ? 'checked' : '';
 const disabled = eligible ? '' : 'disabled';
 const title = eligible ? 'Select for manual check-in' : (isCompleted(a) ? 'Already finished' : 'Already checked in');
 return `<input type="checkbox" class="attendance-row-select" value="${userId}" ${checked} ${disabled} title="${Pyrk.esc(title)}" aria-label="Select ${Pyrk.esc(a.full_name || 'member')}">`;
}

function updateBulkToolbar() {
 const pendingRows = currentAttendanceRows.filter(canBulkCheckIn);
 const pendingIds = new Set(pendingRows.map(attendanceUserId));
 selectedAttendanceUserIds = new Set([...selectedAttendanceUserIds].filter(id => pendingIds.has(Number(id))));

 const selectedCount = selectedAttendanceUserIds.size;
 const countEl = document.getElementById('bulkSelectedCount');
 const eligibleEl = document.getElementById('bulkEligibleCount');
 const bulkBtn = document.getElementById('bulkCheckinBtn');
 const selectAll = document.getElementById('attendanceSelectAll');
 const toolbar = document.getElementById('attendanceBulkToolbar');

 if (countEl) countEl.textContent = `${selectedCount} selected`;
 if (eligibleEl) {
   eligibleEl.textContent = pendingRows.length
     ? `${pendingRows.length} attendee${pendingRows.length === 1 ? '' : 's'} still pending manual check-in.`
     : 'No pending manual check-ins for this walk.';
 }
 if (bulkBtn) bulkBtn.disabled = selectedCount === 0;
 if (toolbar) toolbar.classList.toggle('has-selection', selectedCount > 0);
 if (selectAll) {
   selectAll.disabled = pendingRows.length === 0;
   selectAll.checked = pendingRows.length > 0 && selectedCount === pendingRows.length;
   selectAll.indeterminate = selectedCount > 0 && selectedCount < pendingRows.length;
 }

 document.querySelectorAll('.attendance-row-select').forEach(input => {
   const id = Number(input.value || 0);
   input.checked = selectedAttendanceUserIds.has(id);
 });
}

function statusPillHtml(a) {
 const status = String(a.status || a.registration_status || 'registered');
 const cls = (status === 'finished' || status === 'manual_verified') ? 'ok' : status === 'partially_completed' ? 'warn' : status === 'checked_in' ? 'ok' : 'muted';
 const km = a.verified_km ? `<small>${Number(a.verified_km).toFixed(2)} KM</small>` : '';
 return `<span class="pill ${cls}">${Pyrk.esc(attendanceStatusLabel(a))}</span>${km}`;
}

function checkpointInfo(a) {
 const cp = a.last_checkpoint || null;
 const estimate = Number(a.partial_estimated_km || 0);
 if (!cp) return '<span class="muted">No checkpoint scanned</span>';
 return `<strong>${Pyrk.esc(cp.title || 'Checkpoint')}</strong><small>Estimated partial KM: ${estimate.toFixed(2)}</small>`;
}

function actionButtons(a) {
 const done = isCompleted(a);
 if (done) {
   return `<div class="attendance-complete-warning">
     <strong>Already finished</strong>
     <span>Re-check-in is blocked for this member.</span>
   </div>`;
 }
 const estimate = Number(a.partial_estimated_km || 0);
 return `
   <div class="attendance-actions-pro">
     <button class="btn btn-small" onclick="checkin(${a.user_id})">${isCheckedIn(a) ? 'Already checked in' : 'Check-in'}</button>
     <button class="btn btn-secondary btn-small" onclick="finish(${a.user_id})">Finish full</button>
     <button class="btn btn-light btn-small" onclick="partialManual(${a.user_id}, '${Pyrk.esc(a.full_name || 'member').replace(/'/g, '&#39;')}')">Partial manual</button>
     <button class="btn btn-light btn-small" onclick="partialCheckpoint(${a.user_id}, ${estimate})" ${estimate <= 0 ? 'disabled title="No checkpoint scanned yet"' : ''}>Partial from checkpoint</button>
   </div>`;
}

function populateStationPoints(points = []) {
  currentRoutePoints = points || [];
  const select = document.getElementById('stationPointSelect');
  if (!select) return;
  const usable = currentRoutePoints.filter(p => Number(p.is_required_checkpoint || 0) === 1);
  select.innerHTML = usable.map(p => `<option value="${Number(p.id)}">${Number(p.sort_order || 0)}. ${Pyrk.esc(pointLabel(p.point_type))} — ${Pyrk.esc(p.title || '')}</option>`).join('') || '<option value="">No stations require QR check-in for this walk</option>';
}

async function loadAttendance(){
 const walkId=document.getElementById('walkSelect').value; if(!walkId) return;
 const res=await Pyrk.get('attendance.php',{walk_id:walkId});
 const body=document.getElementById('attendanceBody');
 if(!res.ok){body.innerHTML=`<tr><td colspan="8">${Pyrk.esc(res.message)}</td></tr>`; return;}
 currentAttendanceRows = res.data.attendance || [];
 populateStationPoints(res.data.route_points || []);
 body.innerHTML=currentAttendanceRows.map(a=>`<tr class="${isCompleted(a) ? 'is-completed-row' : ''} ${isCheckedIn(a) ? 'is-checked-in-row' : ''} ${canBulkCheckIn(a) ? 'is-bulk-eligible' : ''}" data-user-id="${attendanceUserId(a)}">
   <td class="select-col">${selectionCheckboxHtml(a)}</td>
   <td>${Pyrk.esc(a.full_name)}<small>${Pyrk.esc(a.mobile || '')}</small></td>
   <td>${Pyrk.esc(a.emergency_contact_mobile||'')}</td>
   <td>${Pyrk.esc(a.medical_conditions||'')}</td>
   <td>${a.waiver_signed_at?'<span class="pill ok">signed</span>':'<span class="pill bad">missing</span>'}</td>
   <td>${statusPillHtml(a)}<small>${a.check_in_time ? 'Checked in: ' + Pyrk.formatDateTime(a.check_in_time) : ''}</small></td>
   <td>${checkpointInfo(a)}</td>
   <td>${actionButtons(a)}</td>
 </tr>`).join('') || '<tr><td colspan="8">No registered attendees.</td></tr>';
 updateBulkToolbar();
}

async function checkin(userId){
 const res=await Pyrk.post('attendance.php',{action:'checkin',walk_id:document.getElementById('walkSelect').value,user_id:userId});
 Pyrk.toast('attendanceMsg',res);
 if (res.ok && res.data?.already_checked_in) alert(res.message || 'This member is already checked in.');
 loadAttendance();
}

async function bulkCheckInSelected(){
 const ids = [...selectedAttendanceUserIds].map(Number).filter(Boolean);
 if (!ids.length) {
   Pyrk.toast('attendanceMsg', {ok:false, message:'Select at least one attendee to check in.'});
   return;
 }
 const label = ids.length === 1 ? '1 selected attendee' : `${ids.length} selected attendees`;
 if (!confirm(`Manual check-in for ${label}?`)) return;
 const button = document.getElementById('bulkCheckinBtn');
 if (button) { button.disabled = true; button.dataset.originalText = button.textContent; button.textContent = 'Checking in...'; }
 const res = await Pyrk.post('attendance.php', {action:'bulk_checkin', walk_id:document.getElementById('walkSelect').value, user_ids:ids});
 Pyrk.toast('attendanceMsg', res);
 selectedAttendanceUserIds.clear();
 if (button) { button.textContent = button.dataset.originalText || 'Check-in selected'; }
 await loadAttendance();
}

async function finish(userId){
 if(!confirm('Mark this member as fully finished? Full route KM and full completion points will be awarded.')) return;
 const res=await Pyrk.post('attendance.php',{action:'finish',walk_id:document.getElementById('walkSelect').value,user_id:userId});
 Pyrk.toast('attendanceMsg',res);
 loadAttendance();
}

async function partialManual(userId, name='member'){
 const km = prompt(`Partial completion for ${name}\nEnter verified KM completed:`);
 if(km === null) return;
 const value = Number(km);
 if(!Number.isFinite(value) || value <= 0){ Pyrk.toast('attendanceMsg',{ok:false,message:'Enter a valid KM greater than 0.'}); return; }
 const res=await Pyrk.post('attendance.php',{action:'partial_finish_manual',walk_id:document.getElementById('walkSelect').value,user_id:userId,verified_km:value});
 Pyrk.toast('attendanceMsg',res); loadAttendance();
}

async function partialCheckpoint(userId, estimate=0){
 if(Number(estimate || 0) <= 0){ Pyrk.toast('attendanceMsg',{ok:false,message:'No checkpoint was scanned for this member yet.'}); return; }
 if(!confirm(`Mark as partially completed from last checkpoint?\nEstimated KM: ${Number(estimate).toFixed(2)}`)) return;
 const res=await Pyrk.post('attendance.php',{action:'partial_finish_checkpoint',walk_id:document.getElementById('walkSelect').value,user_id:userId});
 Pyrk.toast('attendanceMsg',res); loadAttendance();
}

function qrActionPayload(token) {
  const walkId = document.getElementById('walkSelect').value;
  const mode = activeQrMode();
  const payload = {walk_id: walkId, qr_token: token};
  if (mode === 'finish') payload.action = 'finish_qr';
  else if (mode === 'checkpoint') {
    const routePointId = Number(document.getElementById('stationPointSelect')?.value || 0);
    if (!routePointId) return {error: 'Choose the station/checkpoint first.'};
    payload.action = 'checkpoint_qr';
    payload.route_point_id = routePointId;
  } else payload.action = 'checkin_qr';
  return payload;
}

async function processQrToken(token) {
  if (qrBusy) return;
  const payload = qrActionPayload(token);
  if (payload.error) {
    Pyrk.toast('qrMsg', {ok:false, message:payload.error});
    return;
  }
  qrBusy = true;
  const res = await Pyrk.post('attendance.php', payload);
  Pyrk.toast('qrMsg', res);
  if (res.ok && res.data?.already_checked_in) alert(res.message || 'This member is already checked in for this walk.');
  await loadAttendance();
  setTimeout(() => { qrBusy = false; }, 1500);
}

async function startQrScanner() {
  const msg = document.getElementById('qrMsg');
  const startBtn = document.getElementById('startQrBtn');
  const stopBtn = document.getElementById('stopQrBtn');

  if (window.PyrkNativeDevice?.isAvailable('qr')) {
    if (qrBusy) return;
    try {
      if (startBtn) startBtn.disabled = true;
      if (stopBtn) stopBtn.disabled = true;
      msg.textContent = activeQrMode() === 'finish'
        ? 'Opening native finish QR scanner...'
        : activeQrMode() === 'checkpoint'
          ? 'Opening native station QR scanner...'
          : 'Opening native check-in QR scanner...';
      msg.className = 'notice';
      const result = await window.PyrkNativeDevice.scanQr({
        instructions: activeQrMode() === 'finish'
          ? 'Scan the member QR to record finish.'
          : activeQrMode() === 'checkpoint'
            ? 'Scan the member QR for the selected station.'
            : 'Scan the member QR to check in.',
        scanText: 'Scan member QR'
      });
      await processQrToken(result.value);
    } catch (error) {
      const message = error?.message || 'Native QR scan was not completed.';
      if (!/cancel/i.test(message)) {
        msg.textContent = message;
        msg.className = 'notice bad';
      } else {
        msg.textContent = 'QR scan cancelled.';
        msg.className = 'notice';
      }
    } finally {
      if (startBtn) startBtn.disabled = false;
      if (stopBtn) stopBtn.disabled = true;
    }
    return;
  }

  if (!window.Html5Qrcode) {
    msg.textContent = 'QR scanner library did not load. Use manual token fallback.';
    msg.className = 'notice bad';
    return;
  }
  if (qrScanner) await stopQrScanner();
  qrScanner = new Html5Qrcode('qrReader');
  try {
    await qrScanner.start({facingMode: 'environment'}, {fps: 10, qrbox: {width: 250, height: 250}}, decodedText => processQrToken(decodedText));
    startBtn.disabled = true;
    stopBtn.disabled = false;
    msg.textContent = activeQrMode() === 'finish'
      ? 'Finish scanner started. Point the camera at a member QR code.'
      : activeQrMode() === 'checkpoint'
        ? 'Station scanner started. Point the camera at a member QR code.'
        : 'Check-in scanner started. Point the camera at a member QR code.';
    msg.className = 'notice ok';
  } catch (e) {
    msg.textContent = 'Could not start scanner: ' + (e?.message || e);
    msg.className = 'notice bad';
  }
}

async function stopQrScanner() {
  if (qrScanner) {
    await qrScanner.stop().catch(()=>{});
    await qrScanner.clear().catch(()=>{});
    qrScanner = null;
  }
  document.getElementById('startQrBtn').disabled = false;
  document.getElementById('stopQrBtn').disabled = true;
}

document.getElementById('attendanceBody')?.addEventListener('change', e => {
  const input = e.target.closest('.attendance-row-select');
  if (!input) return;
  const userId = Number(input.value || 0);
  if (!userId) return;
  if (input.checked) selectedAttendanceUserIds.add(userId);
  else selectedAttendanceUserIds.delete(userId);
  updateBulkToolbar();
});

document.getElementById('attendanceSelectAll')?.addEventListener('change', e => {
  const pendingIds = currentAttendanceRows.filter(canBulkCheckIn).map(attendanceUserId);
  if (e.target.checked) pendingIds.forEach(id => selectedAttendanceUserIds.add(id));
  else pendingIds.forEach(id => selectedAttendanceUserIds.delete(id));
  updateBulkToolbar();
});

document.getElementById('selectPendingBtn')?.addEventListener('click', () => {
  selectedAttendanceUserIds = new Set(currentAttendanceRows.filter(canBulkCheckIn).map(attendanceUserId));
  updateBulkToolbar();
});

document.getElementById('clearSelectionBtn')?.addEventListener('click', () => {
  selectedAttendanceUserIds.clear();
  updateBulkToolbar();
});

document.getElementById('bulkCheckinBtn')?.addEventListener('click', bulkCheckInSelected);

document.getElementById('startQrBtn')?.addEventListener('click', startQrScanner);
document.getElementById('stopQrBtn')?.addEventListener('click', stopQrScanner);
document.getElementById('manualQrForm')?.addEventListener('submit', e => {
  e.preventDefault();
  const token = document.getElementById('manualQrToken').value.trim();
  if (token) processQrToken(token);
});
document.getElementById('walkSelect')?.addEventListener('change', () => { selectedAttendanceUserIds.clear(); loadAttendance(); });
document.querySelectorAll('input[name="qrMode"]').forEach(input => input.addEventListener('change', () => {
  const msg = document.getElementById('qrMsg');
  if (msg) msg.textContent = '';
  updateQrModeUi();
}));

updateQrModeUi();
loadWalkOptions();
