function nextMilestone(km) {
  const milestones = [10,25,50,100,250,500];
  return milestones.find(m => km < m) || Math.ceil((km + 1) / 100) * 100;
}



function memberLevelFromKm(km) {
  const value = Number(km || 0);
  if (value >= 500) return 'Pyrk Legend';
  if (value >= 250) return 'Elite Walker';
  if (value >= 100) return 'Gold Walker';
  if (value >= 50) return 'Silver Walker';
  if (value >= 10) return 'Bronze Walker';
  return 'Starter';
}

function memberProfileCompleteness(profile) {
  const checks = [
    profile.full_name,
    profile.email,
    profile.mobile,
    profile.emergency_contact_name,
    profile.emergency_contact_mobile,
    profile.profile_photo_path
  ];
  const complete = checks.filter(Boolean).length;
  return Math.round((complete / checks.length) * 100);
}

function memberSafeInitial(name) {
  return String(name || 'P').trim().slice(0, 1).toUpperCase() || 'P';
}

function memberFormattedPhone(phone) {
  const value = String(phone || '').trim();
  return value || 'Ask admin to complete your emergency contact.';
}

let currentMemberProfile = null;

function memberCanEditOwnProfile(profile = currentMemberProfile || {}) {
  return Number(profile?.can_edit_own_profile ?? 1) === 1;
}

function applyMemberSelfProfilePermission(profile = {}) {
  const allowed = memberCanEditOwnProfile(profile);
  for (const id of ['openMemberEditProfile', 'openMemberEditProfileTop']) {
    const button = document.getElementById(id);
    if (button) button.hidden = !allowed;
  }
  const form = document.getElementById('memberSelfProfileForm');
  if (form) form.querySelectorAll('input, select, textarea, button').forEach(control => {
    control.disabled = !allowed;
  });
}

function splitMemberName(fullName = '') {
  const parts = String(fullName || '').trim().split(/\s+/).filter(Boolean);
  if (!parts.length) return { first: '', last: '' };
  if (parts.length === 1) return { first: parts[0], last: '' };
  return { first: parts.shift(), last: parts.join(' ') };
}

function memberProfileField(label, value) {
  const clean = String(value || '').trim();
  return `<div class="member-profile-field-row"><span>${Pyrk.esc(label)}</span><strong>${clean ? Pyrk.esc(clean) : '—'}</strong></div>`;
}

function memberProfileFieldHtml(label, html) {
  return `<div class="member-profile-field-row"><span>${Pyrk.esc(label)}</span><strong>${html || '—'}</strong></div>`;
}

function renderMemberMiniList(rows = [], emptyText = 'Nothing to show yet.', renderer = null) {
  if (!Array.isArray(rows) || !rows.length) return `<p class="muted small">${Pyrk.esc(emptyText)}</p>`;
  return rows.map(renderer || (row => `<div class="member-mini-list-row"><strong>${Pyrk.esc(row.title || row.walk_title || 'Item')}</strong><small>${Pyrk.esc(row.status || row.created_at || '')}</small></div>`)).join('');
}

function renderMemberFullProfile(profile = {}, data = {}) {
  currentMemberProfile = profile || {};
  applyMemberSelfProfilePermission(currentMemberProfile);
  const name = profile.full_name || 'Member';
  const nameParts = splitMemberName(name);
  const points = Number(profile.loyalty_points || 0);
  const walks = Number(profile.total_walks || 0);
  const km = Number(profile.total_kilometers || 0);
  const genderText = String(profile.gender || '').replace(/_/g, ' ');
  const photoConsent = Number(profile.photo_consent || 0) === 1;

  const avatar = document.getElementById('memberFullProfileAvatar');
  if (avatar) {
    if (profile.profile_photo_path) {
      avatar.outerHTML = `<img class="avatar-preview xl" id="memberFullProfileAvatar" src="${Pyrk.esc(String(profile.profile_photo_path).replace(/^\/+/, ''))}" alt="Profile">`;
    } else {
      avatar.textContent = memberSafeInitial(name);
    }
  }

  const setText = (id, value) => { const el = document.getElementById(id); if (el) el.textContent = value; };
  setText('memberFullProfileName', name);
  setText('memberFullProfileEmail', profile.email || 'No email saved');
  setText('memberFullProfilePoints', points.toLocaleString());
  setText('memberFullProfileWalks', walks.toLocaleString());
  setText('memberFullProfileKm', km.toFixed(1));

  const contact = document.getElementById('memberProfileContactFields');
  if (contact) contact.innerHTML = [
    memberProfileField('First name', nameParts.first),
    memberProfileField('Last name', nameParts.last),
    memberProfileField('Email', profile.email),
    memberProfileField('Mobile', profile.mobile),
    memberProfileField('Date of birth', profile.date_of_birth ? Pyrk.formatDate(profile.date_of_birth) : ''),
    memberProfileField('Age', profile.age ? `${profile.age} years` : ''),
    memberProfileField('Gender', genderText),
  ].join('');

  const safety = document.getElementById('memberProfileSafetyFields');
  if (safety) safety.innerHTML = [
    memberProfileField('Emergency contact', profile.emergency_contact_name),
    memberProfileField('Emergency mobile', profile.emergency_contact_mobile),
    memberProfileField('Medical conditions', profile.medical_conditions || 'No medical notes recorded.'),
  ].join('');

  const account = document.getElementById('memberProfileAccountFields');
  if (account) account.innerHTML = [
    memberProfileFieldHtml('Status', statusPill(profile.status || 'active')),
    memberProfileField('Profile editing', memberCanEditOwnProfile(profile) ? 'Allowed' : 'Disabled by administrator'),
    memberProfileField('Photo consent', photoConsent ? 'Approved' : 'Not approved'),
    memberProfileField('QR token', profile.qr_token),
    memberProfileField('Member since', profile.created_at ? Pyrk.formatDate(profile.created_at) : ''),
    memberProfileField('Updated', profile.updated_at ? Pyrk.formatDateTime(profile.updated_at) : ''),
  ].join('');

  const groups = document.getElementById('memberProfileGroups');
  if (groups) {
    const groupRows = data.member_groups || [];
    groups.innerHTML = groupRows.length
      ? groupRows.map(g => `<span class="member-profile-chip">👥 ${Pyrk.esc(g.group_name || 'Group')}</span>`).join('')
      : '<p class="muted small">No groups assigned yet.</p>';
  }

  const waivers = document.getElementById('memberProfileWaivers');
  if (waivers) waivers.innerHTML = renderMemberMiniList(data.waivers || [], 'No signed waivers yet.', w => `
    <div class="member-mini-list-row"><strong>${Pyrk.esc(w.walk_title || 'Walk waiver')}</strong><small>${Pyrk.esc(w.waiver_title || 'Waiver')} ${w.waiver_version ? '· v' + Pyrk.esc(w.waiver_version) : ''} · ${Pyrk.formatDateTime(w.signed_at || w.created_at)}</small></div>`);

  const photos = document.getElementById('memberProfilePhotos');
  if (photos) photos.innerHTML = renderMemberMiniList(data.photos || [], 'No photos uploaded yet.', p => `
    <div class="member-mini-list-row"><strong>${Pyrk.esc(p.title || p.walk_title || 'Photo')}</strong><small>${Pyrk.esc(p.walk_title || '')} · ${Pyrk.esc(String(p.status || '').replace(/_/g, ' '))} · ${Number(p.votes_count || 0)} votes</small></div>`);
}

function fillMemberSelfProfileForm(profile = {}) {
  const parts = splitMemberName(profile.full_name || '');
  const setVal = (id, value) => { const el = document.getElementById(id); if (el) el.value = value || ''; };
  setVal('memberSelfFirstName', parts.first);
  setVal('memberSelfLastName', parts.last);
  setVal('memberSelfFullName', profile.full_name || '');
  setVal('memberSelfEmail', profile.email || '');
  setVal('memberSelfMobile', profile.mobile || '');
  setVal('memberSelfDateOfBirth', profile.date_of_birth ? String(profile.date_of_birth).slice(0, 10) : '');
  setVal('memberSelfGender', profile.gender || '');
  setVal('memberSelfEmergencyName', profile.emergency_contact_name || '');
  setVal('memberSelfEmergencyMobile', profile.emergency_contact_mobile || '');
  setVal('memberSelfMedicalConditions', profile.medical_conditions || '');
  const consent = document.getElementById('memberSelfPhotoConsent');
  if (consent) consent.checked = Number(profile.photo_consent || 0) === 1;
  const preview = document.getElementById('memberSelfProfilePreview');
  if (preview) {
    if (profile.profile_photo_path) {
      preview.outerHTML = `<img class="avatar-preview xl" id="memberSelfProfilePreview" src="${Pyrk.esc(String(profile.profile_photo_path).replace(/^\/+/, ''))}" alt="Profile preview">`;
    } else {
      preview.outerHTML = `<div class="avatar-preview xl" id="memberSelfProfilePreview">${Pyrk.esc(memberSafeInitial(profile.full_name))}</div>`;
    }
  }
}

function openMemberSelfProfileModal() {
  if (!memberCanEditOwnProfile()) {
    alert('Profile editing has been disabled for your account by an administrator.');
    return;
  }
  fillMemberSelfProfileForm(currentMemberProfile || {});
  const modal = document.getElementById('memberSelfProfileModal');
  if (modal) {
    modal.hidden = false;
    modal.scrollTop = 0;
  }
  document.body.classList.add('modal-open', 'member-self-profile-open');
  const msg = document.getElementById('memberSelfProfileMsg');
  if (msg) msg.textContent = '';
}

function closeMemberSelfProfileModal() {
  const modal = document.getElementById('memberSelfProfileModal');
  if (modal) modal.hidden = true;
  document.body.classList.remove('member-self-profile-open');
  if (!document.querySelector('.modal-backdrop:not([hidden])')) {
    document.body.classList.remove('modal-open');
  }
}

function bindMemberSelfProfileEditor() {
  for (const id of ['openMemberEditProfile', 'openMemberEditProfileTop']) {
    const btn = document.getElementById(id);
    if (btn && !btn.dataset.boundProfileEdit) {
      btn.dataset.boundProfileEdit = '1';
      btn.addEventListener('click', openMemberSelfProfileModal);
    }
  }
  document.querySelectorAll('[data-self-profile-close]').forEach(btn => {
    if (btn.dataset.boundProfileClose) return;
    btn.dataset.boundProfileClose = '1';
    btn.addEventListener('click', closeMemberSelfProfileModal);
  });
  const photo = document.getElementById('memberSelfProfilePhoto');
  if (photo && !photo.dataset.boundPreview) {
    photo.dataset.boundPreview = '1';
    photo.addEventListener('change', e => {
      const file = e.target.files && e.target.files[0];
      if (!file) return;
      const url = URL.createObjectURL(file);
      const preview = document.getElementById('memberSelfProfilePreview');
      if (preview) preview.outerHTML = `<img class="avatar-preview xl" id="memberSelfProfilePreview" src="${url}" alt="Profile preview">`;
    });
  }
  const form = document.getElementById('memberSelfProfileForm');
  if (form && !form.dataset.boundSubmit) {
    form.dataset.boundSubmit = '1';
    form.addEventListener('submit', async e => {
      e.preventDefault();
      if (!memberCanEditOwnProfile()) {
        Pyrk.toast('memberSelfProfileMsg', {ok: false, message: 'Profile editing is disabled for your account.'});
        return;
      }
      const first = document.getElementById('memberSelfFirstName')?.value || '';
      const last = document.getElementById('memberSelfLastName')?.value || '';
      const full = document.getElementById('memberSelfFullName');
      if (full) full.value = `${first} ${last}`.trim();
      const fd = new FormData(form);
      fd.append('action', 'update_profile');
      if (!document.getElementById('memberSelfPhotoConsent')?.checked) fd.set('photo_consent', '0');
      const btn = document.getElementById('memberSelfSaveBtn');
      if (btn) { btn.disabled = true; btn.textContent = 'Saving...'; }
      const res = await Pyrk.postForm('account.php', fd);
      Pyrk.toast('memberSelfProfileMsg', res);
      if (btn) { btn.disabled = false; btn.textContent = 'Save profile'; }
      if (res.ok) {
        await loadProfile();
        setTimeout(closeMemberSelfProfileModal, 650);
      }
    });
  }
}

function renderMemberMobileExperience(profile = {}, badges = [], nextWalk = null, history = []) {
  const root = document.getElementById('memberMobileExperience');
  if (!root) return;

  const totalKm = Number(profile.total_kilometers || 0);
  const walks = Number(profile.total_walks || 0);
  const points = Number(profile.loyalty_points || 0);
  const level = memberLevelFromKm(totalKm);
  const completeness = memberProfileCompleteness(profile);
  const milestone = nextMilestone(totalKm);
  const remaining = Math.max(0, milestone - totalKm);
  const milestoneStart = milestone <= 10 ? 0 : (milestone === 25 ? 10 : milestone === 50 ? 25 : milestone === 100 ? 50 : milestone === 250 ? 100 : milestone === 500 ? 250 : milestone - 100);
  const progressPercent = Math.max(0, Math.min(100, Math.round(((totalKm - milestoneStart) / Math.max(1, milestone - milestoneStart)) * 100)));

  const appName = document.getElementById('memberAppName');
  const appMeta = document.getElementById('memberAppMeta');
  const appStatus = document.getElementById('memberAppStatus');
  const appLevel = document.getElementById('memberAppLevel');
  const appAvatar = document.getElementById('memberAppAvatar');

  if (appName) appName.textContent = profile.full_name || 'Pyrk member';
  if (appMeta) appMeta.textContent = `${walks} walks · ${totalKm.toFixed(1)} KM · ${points} points`;
  if (appStatus) appStatus.textContent = String(profile.status || 'member').replace(/_/g, ' ');
  if (appLevel) appLevel.textContent = level;
  if (appAvatar) {
    if (profile.profile_photo_path) {
      appAvatar.innerHTML = `<img src="${Pyrk.esc(String(profile.profile_photo_path).replace(/^\/+/, ''))}" alt="Profile">`;
      appAvatar.classList.add('has-photo');
    } else {
      appAvatar.textContent = memberSafeInitial(profile.full_name);
      appAvatar.classList.remove('has-photo');
    }
  }

  const nextCard = document.getElementById('memberNextWalkCard');
  if (nextCard) {
    if (nextWalk) {
      const date = Pyrk.formatDate(nextWalk.walk_date);
      const start = String(nextWalk.start_time || '').slice(0, 5);
      const finish = String(nextWalk.expected_finish_time || '').slice(0, 5);
      const distance = Number(nextWalk.total_km || nextWalk.verified_km || 0).toFixed(1);
      const today = new Date().toISOString().slice(0, 10) === String(nextWalk.walk_date || '').slice(0, 10);
      nextCard.innerHTML = `
        <div class="member-card-head">
          <div>
            <p class="member-app-label">${today ? 'Today\'s walk' : 'Next registered walk'}</p>
            <h3>${Pyrk.esc(nextWalk.title || 'Upcoming walk')}</h3>
          </div>
          <span class="member-live-dot">${today ? 'Today' : 'Ready'}</span>
        </div>
        <div class="member-next-meta">
          <span><strong>${Pyrk.esc(date)}</strong><small>Date</small></span>
          <span><strong>${Pyrk.esc(start)}${finish ? '–' + Pyrk.esc(finish) : ''}</strong><small>Time</small></span>
          <span><strong>${distance} KM</strong><small>Distance</small></span>
        </div>
        <p class="member-card-muted">${Pyrk.esc(nextWalk.route_name || 'Route will be shown in the walk page.')}</p>
        <a class="member-card-button" href="walk.php?id=${Number(nextWalk.id || nextWalk.walk_id || 0)}">Open walk</a>`;
    } else {
      nextCard.innerHTML = `
        <div class="member-card-head">
          <div>
            <p class="member-app-label">Next step</p>
            <h3>Choose your next walk</h3>
          </div>
          <span class="member-live-dot muted-dot">Open</span>
        </div>
        <p class="member-card-muted">Register for an upcoming event to see your walking plan, QR pass and checkpoint journey here.</p>
        <a class="member-card-button" href="#walks">Browse walks</a>`;
    }
  }

  const progressTitle = document.getElementById('memberProgressTitle');
  const progressPercentText = document.getElementById('memberProgressPercent');
  const progressBar = document.getElementById('memberProgressBar');
  const progressNote = document.getElementById('memberProgressNote');
  if (progressTitle) progressTitle.textContent = `${totalKm.toFixed(1)} KM`;
  if (progressPercentText) {
    progressPercentText.textContent = `${progressPercent}%`;
    const ring = progressPercentText.closest('.member-progress-ring-mini');
    if (ring) ring.style.setProperty('--member-progress', `${progressPercent}%`);
  }
  if (progressBar) progressBar.style.width = `${progressPercent}%`;
  if (progressNote) progressNote.innerHTML = totalKm > 0
    ? `Only <strong>${remaining.toFixed(1)} KM</strong> until your ${milestone} KM milestone. You have ${badges.length} badge${badges.length === 1 ? '' : 's'}.`
    : 'Complete your first walk to start unlocking levels, badges and rewards.';

  const digitalName = document.getElementById('memberDigitalName');
  const digitalEmail = document.getElementById('memberDigitalEmail');
  const digitalStatus = document.getElementById('memberDigitalStatus');
  const digitalPoints = document.getElementById('memberDigitalPoints');
  const emergencyName = document.getElementById('memberEmergencyName');
  const emergencyPhone = document.getElementById('memberEmergencyPhone');
  const safetyNote = document.getElementById('memberSafetyNote');

  if (digitalName) digitalName.textContent = profile.full_name || 'Member';
  if (digitalEmail) digitalEmail.textContent = profile.email || 'No email saved';
  if (digitalPoints) digitalPoints.textContent = Number(points || 0).toLocaleString();
  if (digitalStatus) digitalStatus.textContent = `${level} · ${completeness}% profile ready`;
  if (emergencyName) emergencyName.textContent = profile.emergency_contact_name || 'Not set';
  if (emergencyPhone) emergencyPhone.textContent = memberFormattedPhone(profile.emergency_contact_mobile);
  if (safetyNote) safetyNote.textContent = profile.emergency_contact_mobile ? 'Emergency contact saved' : 'Emergency contact missing';
}

function statusPill(status) {
  const s = String(status || 'unknown');
  const cls = ['active','approved','fulfilled','registered','finished','partially_completed','manual_verified','open','checked in','partially completed'].includes(s) ? 'pill-green' : (['rejected','cancelled','closed'].includes(s) ? 'pill-red' : 'pill-muted');
  return `<span class="pill ${cls}">${Pyrk.esc(s.replace(/_/g, ' '))}</span>`;
}


function walkPaymentText(walk) {
  const model = String(walk?.payment_model || 'free').toLowerCase();
  const amount = Number(walk?.payment_amount || 0);
  const currency = String(walk?.payment_currency || 'LBP').toUpperCase();
  if (model !== 'paid' || amount <= 0) return 'Free';
  return `${amount.toLocaleString(undefined, {minimumFractionDigits: amount % 1 ? 2 : 0, maximumFractionDigits: 2})} ${currency}`;
}

function walkPaymentPill(walk) {
  const paid = String(walk?.payment_model || 'free').toLowerCase() === 'paid' && Number(walk?.payment_amount || 0) > 0;
  return `<span class="pill ${paid ? 'payment-pill-paid' : 'payment-pill-free'}">${paid ? 'Paid: ' + Pyrk.esc(walkPaymentText(walk)) : 'Free'}</span>`;
}


function walkIsFinishedForMe(walk) {
  const status = String(walk?.my_attendance_status || '').toLowerCase();
  return Number(walk?.is_finished_by_me || 0) === 1
    || status === 'finished'
    || status === 'manual_verified'
    || (!!walk?.my_finish_time && status !== 'partially_completed');
}

function walkDashboardStatus(walk) {
  const attendanceStatus = String(walk?.my_attendance_status || '').toLowerCase();
  if (attendanceStatus === 'partially_completed') return 'partially completed';
  if (attendanceStatus === 'manual_verified') return 'finished';
  if (walkIsFinishedForMe(walk)) return 'finished';
  if (attendanceStatus === 'checked_in' || attendanceStatus === 'started') return 'checked in';
  if (Number(walk?.is_registered || 0) === 1 || ['registered','approved'].includes(String(walk?.my_registration_status || '').toLowerCase())) return 'registered';
  return '';
}



function pointLedgerTypeLabel(type) {
  return ({
    walk_completed: 'Walk',
    badge_earned: 'Badge',
    photo_winner: 'Photo winner',
    manual_reward: 'Manual reward',
    adjustment: 'Adjustment',
    reward_claim: 'Prize claim',
    reward_refund: 'Prize refund'
  })[String(type || '')] || String(type || 'points').replace(/_/g, ' ');
}

function renderPointsLedger(rows = [], currentPoints = 0) {
  const body = document.getElementById('pointsLedgerBody');
  const summary = document.getElementById('pointsLedgerSummary');
  if (!body) return;

  const gained = rows.filter(r => Number(r.points || 0) > 0).reduce((sum, r) => sum + Number(r.points || 0), 0);
  const used = rows.filter(r => Number(r.points || 0) < 0).reduce((sum, r) => sum + Math.abs(Number(r.points || 0)), 0);

  if (summary) {
    summary.innerHTML = `
      <span><strong>${Number(currentPoints || 0)}</strong><em>current</em></span>
      <span class="gain"><strong>+${gained}</strong><em>gained</em></span>
      <span class="use"><strong>-${used}</strong><em>used</em></span>`;
  }

  body.innerHTML = rows.map(r => {
    const points = Number(r.points || 0);
    const positive = points >= 0;
    return `<tr>
      <td>${Pyrk.formatDateTime(r.created_at)}</td>
      <td><span class="ledger-type-pill">${Pyrk.esc(pointLedgerTypeLabel(r.transaction_type))}</span></td>
      <td><strong>${Pyrk.esc(r.description || 'Points update')}</strong></td>
      <td>${Pyrk.esc(r.walk_title || '—')}</td>
      <td><span class="ledger-points ${positive ? 'is-gain' : 'is-use'}">${positive ? '+' : ''}${points}</span></td>
    </tr>`;
  }).join('') || '<tr><td colspan="5" class="muted">No point transactions yet. Complete a walk or claim a prize to start your ledger.</td></tr>';
}


async function loadProfile(){
  const res = await Pyrk.get('members.php', {action:'profile'});
  if(!res.ok) return;
  const p = res.data.profile || {};
  const badges = res.data.badges || [];
  renderMemberFullProfile(p, res.data || {});
  bindMemberSelfProfileEditor();
  const totalKm = Number(p.total_kilometers || 0);
  const heroName = document.getElementById('clientHeroName');
  const heroMeta = document.getElementById('clientHeroMeta');
  const heroAvatar = document.getElementById('clientHeroAvatar');
  if (heroName) heroName.textContent = p.full_name || 'My profile';
  if (heroMeta) heroMeta.textContent = `${Number(p.total_walks || 0)} walks · ${totalKm.toFixed(1)} KM · ${Number(p.loyalty_points || 0)} points`;
  if (heroAvatar && p.profile_photo_path) heroAvatar.outerHTML = `<img class="avatar-preview xl" id="clientHeroAvatar" src="${Pyrk.esc(String(p.profile_photo_path).replace(/^\/+/, ''))}" alt="Profile">`;
  else if (heroAvatar) heroAvatar.textContent = String(p.full_name || 'P').slice(0,1).toUpperCase();
  const milestone = nextMilestone(totalKm);
  document.getElementById('statWalks').textContent = p.total_walks || 0;
  document.getElementById('statKm').textContent = totalKm.toFixed(1);
  document.getElementById('statPoints').textContent = p.loyalty_points || 0;
  document.getElementById('statBadges').textContent = badges.length;
  document.getElementById('progressKm').textContent = totalKm.toFixed(1);
  document.getElementById('progressText').innerHTML = totalKm > 0 ? `You are <strong>${Math.max(0, milestone - totalKm).toFixed(1)} KM</strong> away from the ${milestone} KM milestone.` : 'Complete your first walk to start collecting kilometers and badges.';
  renderPointsLedger(res.data.points_ledger || [], Number(p.loyalty_points || 0));

  const next = res.data.next_walk;
  renderMemberMobileExperience(p, badges, next, res.data.history || []);
  document.getElementById('nextWalkBox').innerHTML = next ? `<h3>Next registered walk</h3><p><strong>${Pyrk.esc(next.title)}</strong></p><p>${Pyrk.formatDate(next.walk_date)} at ${String(next.start_time).slice(0,5)} · ${Number(next.total_km || 0).toFixed(1)} KM</p>` : '<h3>No registered walk yet</h3><p>Choose an upcoming walk and register to join the club activity.</p>';

  document.getElementById('badgesList').innerHTML = badges.map(b => `<div class="badge-pro-item"><span>${Pyrk.esc(b.badge_icon||'🏅')}</span><div><strong>${Pyrk.esc(b.badge_name)}</strong><small>${Pyrk.esc(b.description||'')}</small></div></div>`).join('') || '<div class="empty-mini"><strong>No badges yet</strong><p>Complete a walk to earn your first badge.</p></div>';
  document.getElementById('historyBody').innerHTML = (res.data.history || []).map(h => `<tr><td>${Pyrk.esc(h.title)}<small>${Pyrk.esc(h.route_name || '')}</small></td><td>${Pyrk.formatDate(h.walk_date)}</td><td>${statusPill(h.status || (h.finish_time ? 'finished' : 'registered'))}</td><td>${Pyrk.esc(h.verified_km||'0.00')}</td></tr>`).join('') || '<tr><td colspan="4">No completed walks yet.</td></tr>';
}

async function loadWalks(){
  const res = await Pyrk.get('walks.php');
  const box = document.getElementById('walksList');
  if(!res.ok){ box.innerHTML = `<p class="bad">${Pyrk.esc(res.message)}</p>`; return; }
  renderMemberPriorityWalkAction(res.data.walks || []);
  box.innerHTML = (res.data.walks || []).map(w => {
    const status = walkDashboardStatus(w);
    const registered = status === 'registered' || status === 'checked in' || status === 'finished' || status === 'partially completed';
    const finished = status === 'finished' || status === 'partially completed';
    const walkDescription = String(w.description || w.route_description || '').trim();
    const descriptionLine = walkDescription ? `<p class="muted walk-card-description">${Pyrk.esc(walkDescription)}</p>` : '';
    return `<article class="walk-card ${registered ? 'walk-card-registered' : ''} ${finished ? 'walk-card-finished' : ''}">
    <div class="date-chip"><strong>${Pyrk.formatDate(w.walk_date).slice(0,2)}</strong><span>${Pyrk.formatDate(w.walk_date).slice(3,5)}</span></div>
    <div class="walk-card-body"><div class="inline-controls tiny-controls"><span class="pill ${w.access_type === 'invitation_only' ? 'pill-red' : 'pill-green'}">${w.access_type === 'invitation_only' ? 'Invitation only' : 'Open'}</span>${walkPaymentPill(w)}${status ? statusPill(status) : ''}</div><h3>${Pyrk.esc(w.title)}</h3><p>${Pyrk.esc(w.route_name)} · ${Number(w.total_km || 0).toFixed(1)} KM</p><p class="muted">${String(w.start_time).slice(0,5)} → ${String(w.expected_finish_time).slice(0,5)}</p>${descriptionLine}${finished ? `<p class="walk-finished-note">${status === 'partially completed' ? 'Partially completed' : 'Finished'}${w.my_finish_time ? ' · ' + Pyrk.formatDateTime(w.my_finish_time) : ''}${w.my_verified_km ? ' · ' + Number(w.my_verified_km).toFixed(1) + ' KM verified' : ''}</p>` : ''}</div>
    <div class="walk-card-actions"><a class="btn btn-small ${registered ? 'btn-light' : ''}" href="walk.php?id=${w.id}">${finished ? (status === 'partially completed' ? 'View partial walk' : 'View finished walk') : (registered ? 'View registered walk' : 'Open')}</a></div>
  </article>`;
  }).join('') || '<p>No upcoming walks.</p>';
}


function renderMemberPriorityWalkAction(walks = []) {
  const panel = document.getElementById('memberPriorityWalkAction');
  if (!panel) return;
  const label = document.getElementById('priorityWalkLabel');
  const title = document.getElementById('priorityWalkTitle');
  const text = document.getElementById('priorityWalkText');
  const button = document.getElementById('priorityWalkButton');
  const list = Array.isArray(walks) ? walks : [];

  const active = list.filter(w => !walkIsFinishedForMe(w));
  let chosen = active.find(w => Number(w.is_registered || 0) !== 1 && Number(w.waiver_required || 0) === 1)
    || active.find(w => Number(w.is_registered || 0) !== 1)
    || active.find(w => Number(w.is_registered || 0) === 1)
    || null;

  if (!chosen) {
    panel.hidden = true;
    panel.classList.remove('is-visible');
    return;
  }

  const isRegistered = Number(chosen.is_registered || 0) === 1 || ['registered','approved'].includes(String(chosen.my_registration_status || '').toLowerCase());
  const needsWaiver = !isRegistered && Number(chosen.waiver_required || 0) === 1;
  const walkUrl = `walk.php?id=${Number(chosen.id || chosen.walk_id || 0)}`;
  const route = chosen.route_name ? ` · ${Pyrk.esc(chosen.route_name)}` : '';
  const date = chosen.walk_date ? Pyrk.formatDate(chosen.walk_date) : 'Upcoming';
  const time = chosen.start_time ? String(chosen.start_time).slice(0,5) : '';

  panel.hidden = false;
  panel.classList.add('is-visible');
  if (label) label.textContent = isRegistered ? 'Registered walk' : (needsWaiver ? 'Action required' : 'Join next walk');
  if (title) title.textContent = chosen.title || 'Upcoming walk';
  if (text) text.innerHTML = isRegistered
    ? `You are registered. Open the walk page for QR check-in, route details and photo upload.<br><small>${date}${time ? ' · ' + time : ''}${route}</small>`
    : (needsWaiver
      ? `Sign the waiver to automatically complete your registration.<br><small>${date}${time ? ' · ' + time : ''}${route}</small>`
      : `Register now for this walk.<br><small>${date}${time ? ' · ' + time : ''}${route}</small>`);
  if (button) {
    button.href = walkUrl;
    button.textContent = isRegistered ? 'Open walk' : (needsWaiver ? 'Sign waiver & register' : 'Register now');
  }
}

function rewardIconFor(name, type) {
  const n = String(name || '').toLowerCase();
  const t = String(type || '').toLowerCase();
  if (n.includes('coffee') || n.includes('cafe')) return '☕';
  if (n.includes('bottle') || n.includes('water')) return '💧';
  if (n.includes('shirt') || n.includes('t-shirt') || n.includes('tshirt')) return '👕';
  if (n.includes('medal') || n.includes('badge')) return '🏅';
  if (n.includes('voucher') || n.includes('coupon')) return '🎟️';
  if (n.includes('bag') || n.includes('kit')) return '🎒';
  if (t === 'points') return '⭐';
  return '🎁';
}

function renderRewardStore(data) {
  const header = document.getElementById('rewardStoreHeader');
  const store = document.getElementById('rewardStore');
  const claims = document.getElementById('rewardClaimsBody');
  if (!store) return;

  const points = Number(data.loyalty_points || 0);
  const rewards = data.rewards || [];
  const claimRows = data.claims || [];
  const claimableCount = rewards.filter(r => {
    const cost = Number(r.points_cost || 0);
    const inStock = r.stock_quantity === null || r.stock_quantity === undefined || Number(r.stock_quantity) > 0;
    return points >= cost && inStock;
  }).length;

  if (header) {
    header.innerHTML = `
      <div class="reward-wallet-pro">
        <span class="reward-wallet-label">Available balance</span>
        <strong>${points}</strong>
        <small>loyalty points</small>
      </div>
      <div class="reward-kpi-pro">
        <span>Ready now</span>
        <strong>${claimableCount}</strong>
        <small>claimable prizes</small>
      </div>
      <div class="reward-info-pro">
        <strong>How claiming works</strong>
        <p>Pick a prize, submit your claim, and points are reserved immediately. Pyrk will approve and prepare the reward.</p>
      </div>`;
  }

  store.innerHTML = rewards.map(r => {
    const cost = Number(r.points_cost || 0);
    const rawStock = r.stock_quantity;
    const stockUnlimited = rawStock === null || rawStock === undefined || rawStock === '';
    const stockQty = stockUnlimited ? null : Number(rawStock);
    const inStock = stockUnlimited || stockQty > 0;
    const canClaim = points >= cost && inStock;
    const needed = Math.max(0, cost - points);
    const progress = cost > 0 ? Math.min(100, Math.round((points / cost) * 100)) : 100;
    const stockText = stockUnlimited ? 'Unlimited' : `${stockQty} left`;
    const stateText = !inStock ? 'Out of stock' : (canClaim ? 'Ready to claim' : `${needed} pts needed`);
    const stateClass = !inStock ? 'is-out' : (canClaim ? 'is-ready' : 'is-locked');
    const icon = rewardIconFor(r.reward_name, r.reward_type);

    return `<article class="reward-tile-pro ${stateClass}">
      <div class="reward-tile-top">
        <div class="reward-icon-pro">${icon}</div>
        <div class="reward-status-pro">${Pyrk.esc(stateText)}</div>
      </div>

      <div class="reward-tile-body">
        <h3>${Pyrk.esc(r.reward_name)}</h3>
        <p>${Pyrk.esc(r.description || 'Pyrk member reward')}</p>
      </div>

      <div class="reward-meta-pro">
        <span><b>${cost}</b> points</span>
        <span>${Pyrk.esc(stockText)}</span>
      </div>

      <div class="reward-progress-pro" aria-label="Reward progress">
        <div><i style="width:${progress}%"></i></div>
        <small>${progress}% of required points</small>
      </div>

      <button class="btn reward-claim-button-pro" ${canClaim ? '' : 'disabled'} onclick="claimReward(${r.id}, '${Pyrk.esc(r.reward_name).replace(/'/g, '&#39;')}', ${cost})">
        ${canClaim ? 'Claim reward' : (!inStock ? 'Unavailable' : `Need ${needed} pts`)}
      </button>
    </article>`;
  }).join('') || `
    <div class="reward-empty-pro">
      <strong>No prizes available yet</strong>
      <p>Keep walking and collecting points. Pyrk will add rewards soon.</p>
    </div>`;

  if (claims) {
    claims.innerHTML = claimRows.map(c => `<tr>
      <td><strong>${Pyrk.esc(c.reward_name)}</strong></td>
      <td>${statusPill(c.status)}</td>
      <td>${Number(c.points_spent || c.points_cost || 0)}</td>
      <td>${Pyrk.formatDateTime(c.requested_at || c.created_at)}</td>
    </tr>`).join('') || '<tr><td colspan="4" class="muted">No prize claims yet.</td></tr>';
  }
}

async function loadRewards(){
  const res = await Pyrk.get('rewards.php', {action:'store'});
  if (!res.ok) {
    const store = document.getElementById('rewardStore');
    if (store) store.innerHTML = `<p class="bad">${Pyrk.esc(res.message)}</p>`;
    return;
  }
  renderRewardStore(res.data || {});
}

async function claimReward(rewardId, rewardName, cost){
  if (!confirm(`Claim ${rewardName} for ${cost} points? Your points will be deducted immediately.`)) return;
  const res = await Pyrk.post('rewards.php', {action:'claim', reward_id: rewardId});
  alert(res.message || (res.ok ? 'Claim submitted.' : 'Claim failed.'));
  if (res.ok) { await loadProfile(); await loadRewards(); }
}
window.loadRewards = loadRewards;
window.claimReward = claimReward;

loadProfile();
loadWalks();
loadRewards();
