(function(){
  'use strict';

  const page = document.body?.dataset.mobilePage || '';
  let profileCache = null;
  let canEditOwnProfile = true;

  try {
    localStorage.setItem('pyrk_native_app', '1');
    sessionStorage.setItem('pyrk_native_app', '1');
  } catch (e) {}

  const esc = value => Pyrk.esc(value ?? '');
  const byId = id => document.getElementById(id);
  const number = value => Number(value || 0);

  function mediaUrl(path) {
    const value = String(path || '').trim();
    if (!value) return '';
    if (/^(?:https?:)?\/\//i.test(value) || value.startsWith('/')) return value;
    return value.replace(/^\.\//, '');
  }

  function firstName(fullName) {
    return String(fullName || 'Member').trim().split(/\s+/)[0] || 'Member';
  }

  function splitName(fullName) {
    const parts = String(fullName || '').trim().split(/\s+/).filter(Boolean);
    return {first: parts.shift() || '', last: parts.join(' ')};
  }

  function dateParts(value) {
    const formatted = Pyrk.formatDate(value);
    const parts = String(formatted || '').split('/');
    return {day: parts[0] || '—', month: parts[1] || '', year: parts[2] || ''};
  }

  function monthName(value) {
    const raw = String(value || '').slice(0,10);
    const date = new Date(raw + 'T12:00:00');
    return Number.isNaN(date.getTime()) ? '' : date.toLocaleDateString(undefined, {month:'short'});
  }

  function time(value) {
    return value ? String(value).slice(0,5) : '—';
  }

  function statusText(value) {
    return String(value || 'registered').replace(/_/g,' ');
  }

  function setUnread(count) {
    const value = Math.max(0, number(count));
    document.querySelectorAll('[data-mobile-unread-count]').forEach(el => {
      el.textContent = value > 99 ? '99+' : String(value);
      el.hidden = value <= 0;
    });
    document.querySelectorAll('[data-mobile-unread-text]').forEach(el => {
      el.textContent = value ? `${value} unread message${value === 1 ? '' : 's'}` : 'No unread messages';
      el.closest('.mobile-notification-tile')?.classList.toggle('has-unread', value > 0);
    });
  }

  async function loadUnread() {
    const res = await Pyrk.get('mobile_member.php', {action:'unread_count'});
    if (res.ok) setUnread(res.data.unread_count || 0);
  }

  function setAvatar(container, path, name) {
    if (!container) return;
    const src = mediaUrl(path);
    if (src) container.innerHTML = `<img src="${esc(src)}" alt="${esc(name || 'Profile')}">`;
    else container.textContent = String(name || 'P').trim().slice(0,1).toUpperCase() || 'P';
  }

  function errorCard(message) {
    return `<div class="mobile-error-card">${esc(message || 'Could not load this section.')}</div>`;
  }

  function emptyCard(title, text) {
    return `<div class="mobile-empty-card"><strong>${esc(title)}</strong><br><small>${esc(text || '')}</small></div>`;
  }

  async function loadHome() {
    const res = await Pyrk.get('mobile_member.php', {action:'home'});
    if (!res.ok) {
      byId('mobileNextWalk').innerHTML = errorCard(res.message);
      return;
    }
    const data = res.data || {};
    const profile = data.profile || {};
    const name = profile.full_name || 'Member';
    setAvatar(byId('mobileHomeAvatar'), profile.profile_photo_path, name);
    byId('mobileHomeName').textContent = firstName(name);
    byId('mobileHomeMeta').textContent = `${number(profile.total_walks)} walks · ${number(profile.total_kilometers).toFixed(1)} KM`;
    byId('mobileHomeKm').textContent = number(profile.total_kilometers).toFixed(1);
    byId('mobileHomePoints').textContent = number(profile.loyalty_points).toLocaleString();
    byId('mobileHomeBadges').textContent = number(data.badges_count).toLocaleString();
    setUnread(data.unread_count || 0);
    byId('mobileHomeAvatarButton')?.addEventListener('click', () => location.href = 'mobile_profile.php');

    const next = data.next_walk;
    if (!next) {
      byId('mobileNextWalk').innerHTML = `<article><div class="mobile-next-head"><div><p class="mobile-kicker">Next walk</p><h2>No registered walk yet</h2></div><span class="mobile-status-chip">Open</span></div><p class="mobile-card-copy">Browse upcoming walks and choose your next Pyrk activity.</p><a class="mobile-primary-link" href="mobile_walks.php">Browse upcoming walks</a></article>`;
      return;
    }
    byId('mobileNextWalk').innerHTML = `<article>
      <div class="mobile-next-head"><div><p class="mobile-kicker">Next registered walk</p><h2>${esc(next.title || 'Upcoming walk')}</h2></div><span class="mobile-status-chip">${esc(statusText(next.attendance_status || next.registration_status || 'registered'))}</span></div>
      <div class="mobile-next-meta"><span><strong>${esc(Pyrk.formatDate(next.walk_date))}</strong><small>Date</small></span><span><strong>${esc(time(next.start_time))}</strong><small>Start</small></span><span><strong>${number(next.total_km).toFixed(1)} KM</strong><small>Distance</small></span></div>
      <p class="mobile-card-copy">${esc(next.route_name || 'Route details are available in the walk page.')}</p>
      <a class="mobile-primary-link" href="walk.php?id=${number(next.id)}&source=app">Open walk</a>
    </article>`;
  }

  function walkMemberStatus(walk) {
    const attendance = statusText(walk.my_attendance_status || '').toLowerCase();
    if (walk.is_finished_by_me || attendance === 'finished' || attendance === 'manual verified') return 'finished';
    if (walk.is_partially_completed_by_me || attendance === 'partially completed') return 'partially completed';
    if (walk.my_check_in_time || attendance === 'checked in' || attendance === 'started') return 'checked in';
    if (walk.is_registered || walk.my_registration_status) return 'registered';
    return '';
  }

  function renderWalks(rows) {
    const box = byId('mobileWalksList');
    if (!rows.length) {
      box.innerHTML = emptyCard('No upcoming walks', 'New Pyrk walks will appear here when they are published.');
      return;
    }
    box.innerHTML = rows.map(w => {
      const d = dateParts(w.walk_date);
      const memberStatus = walkMemberStatus(w);
      const access = String(w.access_type || '') === 'invitation_only' ? 'Invitation only' : 'Open';
      return `<article class="mobile-walk-card">
        <div class="mobile-date-block"><strong>${esc(d.day)}</strong><span>${esc(monthName(w.walk_date))}</span></div>
        <div class="mobile-card-copy"><h3>${esc(w.title || 'Walk')}</h3><p>${esc(w.route_name || 'Route')} · ${number(w.total_km).toFixed(1)} KM</p><p>${esc(time(w.start_time))}${w.expected_finish_time ? ' – ' + esc(time(w.expected_finish_time)) : ''}</p><div class="mobile-card-tags"><span class="mobile-tag ${access === 'Open' ? 'is-green' : 'is-red'}">${esc(access)}</span>${memberStatus ? `<span class="mobile-tag is-green">${esc(memberStatus)}</span>` : ''}</div></div>
        <div class="mobile-card-action"><a href="walk.php?id=${number(w.id)}&source=app">${memberStatus ? 'Open my walk' : 'View & register'}</a></div>
      </article>`;
    }).join('');
  }

  async function loadWalks() {
    const box = byId('mobileWalksList');
    const res = await Pyrk.get('walks.php', {action:'upcoming'});
    if (!res.ok) { box.innerHTML = errorCard(res.message); return; }
    renderWalks(res.data.walks || []);
  }

  function renderHistory(rows) {
    const box = byId('mobileHistoryList');
    if (!rows.length) { box.innerHTML = emptyCard('No walk history yet', 'Your finished and checked-in walks will appear here.'); return; }
    box.innerHTML = rows.map(row => `<article class="mobile-history-card">
      <div class="mobile-history-head"><div><p class="mobile-kicker">${esc(statusText(row.status))}</p><h3>${esc(row.title || 'Walk')}</h3></div><time>${esc(Pyrk.formatDate(row.walk_date))}</time></div>
      <p class="mobile-card-copy">${esc(row.route_name || 'Route')}</p>
      <div class="mobile-history-meta"><span><small>KM</small><strong>${number(row.verified_km).toFixed(1)}</strong></span><span><small>Check-in</small><strong>${row.check_in_time ? esc(time(String(row.check_in_time).slice(11))) : '—'}</strong></span><span><small>Finished</small><strong>${row.finish_time ? esc(time(String(row.finish_time).slice(11))) : '—'}</strong></span></div>
      <div class="mobile-card-action"><a href="walk.php?id=${number(row.walk_id)}&source=app">View walk</a></div>
    </article>`).join('');
  }

  async function loadHistory() {
    const box = byId('mobileHistoryList');
    const res = await Pyrk.get('mobile_member.php', {action:'history'});
    if (!res.ok) { box.innerHTML = errorCard(res.message); return; }
    setUnread(res.data.unread_count || 0);
    renderHistory(res.data.history || []);
  }

  function activityIcon(type) {
    const value = String(type || '').toLowerCase();
    if (value.includes('walk')) return '🥾';
    if (value.includes('badge')) return '🏅';
    if (value.includes('reward')) return '🎁';
    if (value.includes('photo')) return '📸';
    return '⭐';
  }

  function renderActivity(rows) {
    const box = byId('mobileActivityList');
    if (!rows.length) { box.innerHTML = emptyCard('No points activity yet', 'Complete walks and earn badges to start your points history.'); return; }
    box.innerHTML = rows.map(row => {
      const pts = number(row.points);
      return `<article class="mobile-activity-row"><div class="mobile-activity-icon">${activityIcon(row.transaction_type)}</div><div class="mobile-activity-copy"><strong>${esc(row.description || statusText(row.transaction_type))}</strong><small>${esc(Pyrk.formatDateTime(row.created_at))}${row.walk_title ? ' · ' + esc(row.walk_title) : ''}</small></div><div class="mobile-points-value ${pts >= 0 ? 'is-gain' : 'is-use'}">${pts >= 0 ? '+' : ''}${pts}</div></article>`;
    }).join('');
  }

  async function loadActivity() {
    const box = byId('mobileActivityList');
    const res = await Pyrk.get('mobile_member.php', {action:'activity'});
    if (!res.ok) { box.innerHTML = errorCard(res.message); return; }
    byId('mobileCurrentPoints').textContent = number(res.data.current_points).toLocaleString();
    byId('mobileGainedPoints').textContent = '+' + number(res.data.gained_points).toLocaleString();
    byId('mobileUsedPoints').textContent = '-' + number(res.data.used_points).toLocaleString();
    setUnread(res.data.unread_count || 0);
    renderActivity(res.data.transactions || []);
  }

  function rewardIcon(name) {
    const n = String(name || '').toLowerCase();
    if (n.includes('coffee') || n.includes('cafe')) return '☕';
    if (n.includes('shirt')) return '👕';
    if (n.includes('bottle') || n.includes('water')) return '💧';
    if (n.includes('voucher') || n.includes('coupon')) return '🎟️';
    if (n.includes('bag')) return '🎒';
    return '🎁';
  }

  function renderRewards(storeData, profileData) {
    const points = number(storeData.loyalty_points);
    byId('mobileRewardPoints').textContent = points.toLocaleString();
    const rewards = storeData.rewards || [];
    const store = byId('mobileRewardStore');
    store.innerHTML = rewards.length ? rewards.map(r => {
      const cost = number(r.points_cost);
      const stockUnlimited = r.stock_quantity === null || r.stock_quantity === undefined || r.stock_quantity === '';
      const inStock = stockUnlimited || number(r.stock_quantity) > 0;
      const canClaim = inStock && points >= cost;
      return `<article class="mobile-reward-card"><div class="mobile-reward-icon">${rewardIcon(r.reward_name)}</div><h3>${esc(r.reward_name || 'Reward')}</h3><p>${esc(r.description || 'Pyrk member reward')}</p><div class="mobile-reward-cost"><span>${cost} points</span><span>${stockUnlimited ? 'Available' : number(r.stock_quantity) + ' left'}</span></div><button type="button" data-reward-id="${number(r.id)}" data-reward-name="${esc(r.reward_name || 'Reward')}" data-reward-cost="${cost}" ${canClaim ? '' : 'disabled'}>${canClaim ? 'Claim reward' : (!inStock ? 'Unavailable' : `Need ${Math.max(0,cost-points)} pts`)}</button></article>`;
    }).join('') : emptyCard('No rewards available', 'Keep collecting points. New rewards will appear here.');

    const claims = storeData.claims || [];
    byId('mobileRewardClaims').innerHTML = claims.length ? claims.map(c => `<article class="mobile-claim-card"><div><strong>${esc(c.reward_name || 'Reward')}</strong><small>${esc(Pyrk.formatDateTime(c.requested_at || c.created_at))}</small></div><div><b>${number(c.points_spent || c.points_cost)} pts</b><small>${esc(statusText(c.status))}</small></div></article>`).join('') : emptyCard('No prize claims yet', 'Your claimed rewards will appear here.');

    const badges = profileData.badges || [];
    byId('mobileBadgesList').innerHTML = badges.length ? badges.map(b => `<article class="mobile-badge-row"><span>${esc(b.badge_icon || '🏅')}</span><div><strong>${esc(b.badge_name || 'Badge')}</strong><small>${esc(b.description || '')}${b.earned_at ? ' · ' + esc(Pyrk.formatDate(b.earned_at)) : ''}</small></div></article>`).join('') : emptyCard('No badges yet', 'Complete walks and challenges to unlock badges.');
  }

  async function loadRewards() {
    const [storeRes, profileRes] = await Promise.all([
      Pyrk.get('rewards.php', {action:'store'}),
      Pyrk.get('mobile_member.php', {action:'profile'})
    ]);
    if (!storeRes.ok) { byId('mobileRewardStore').innerHTML = errorCard(storeRes.message); return; }
    if (!profileRes.ok) { byId('mobileBadgesList').innerHTML = errorCard(profileRes.message); }
    setUnread(profileRes.ok ? profileRes.data.unread_count || 0 : 0);
    renderRewards(storeRes.data || {}, profileRes.ok ? profileRes.data || {} : {});
  }

  async function claimReward(button) {
    const id = number(button.dataset.rewardId);
    const name = button.dataset.rewardName || 'this reward';
    const cost = number(button.dataset.rewardCost);
    if (!id || !confirm(`Claim ${name} for ${cost} points?`)) return;
    button.disabled = true;
    const res = await Pyrk.post('rewards.php', {action:'claim', reward_id:id});
    alert(res.message || (res.ok ? 'Claim submitted.' : 'Claim failed.'));
    await loadRewards();
  }

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

  function fillProfileForm(profile) {
    const names = splitName(profile.full_name || '');
    byId('mobileProfileFirstName').value = names.first;
    byId('mobileProfileLastName').value = names.last;
    byId('mobileProfileFullName').value = profile.full_name || '';
    byId('mobileProfileEditEmail').value = profile.email || '';
    byId('mobileProfileMobile').value = profile.mobile || '';
    byId('mobileProfileDob').value = profile.date_of_birth || '';
    byId('mobileProfileGender').value = profile.gender || '';
    byId('mobileProfileEmergencyName').value = profile.emergency_contact_name || '';
    byId('mobileProfileEmergencyMobile').value = profile.emergency_contact_mobile || '';
    byId('mobileProfileMedical').value = profile.medical_conditions || '';
    byId('mobileProfileConsent').checked = number(profile.photo_consent) === 1;
    setAvatar(byId('mobileProfileEditPreview'), profile.profile_photo_path, profile.full_name);
  }

  function openPhoto(src, title, meta) {
    if (!src) return;
    byId('mobilePhotoViewerImage').src = src;
    byId('mobilePhotoViewerTitle').textContent = title || 'Photo';
    byId('mobilePhotoViewerMeta').textContent = meta || '';
    byId('mobilePhotoViewer').hidden = false;
    document.body.style.overflow = 'hidden';
  }

  function closePhoto() {
    byId('mobilePhotoViewer').hidden = true;
    byId('mobilePhotoViewerImage').removeAttribute('src');
    document.body.style.overflow = '';
  }

  function renderProfile(data) {
    profileCache = data.profile || {};
    const p = profileCache;
    canEditOwnProfile = number(p.can_edit_own_profile ?? 1) === 1;
    const editButton = byId('mobileOpenProfileEdit');
    const permissionNotice = byId('mobileProfilePermissionNotice');
    if (editButton) editButton.hidden = !canEditOwnProfile;
    if (permissionNotice) {
      permissionNotice.hidden = canEditOwnProfile;
      permissionNotice.textContent = canEditOwnProfile ? '' : 'Profile editing has been disabled for your account by an administrator. You can still view your details.';
      permissionNotice.className = 'mobile-form-message' + (canEditOwnProfile ? '' : ' is-bad');
    }
    if (!canEditOwnProfile && !byId('mobileProfileEditSheet')?.hidden) closeProfileEdit();
    const name = p.full_name || 'Member';
    setAvatar(byId('mobileProfileAvatar'), p.profile_photo_path, name);
    byId('mobileProfileName').textContent = name;
    byId('mobileProfileEmail').textContent = p.email || 'No email saved';
    byId('mobileProfileWalks').textContent = number(p.total_walks).toLocaleString();
    byId('mobileProfileKm').textContent = number(p.total_kilometers).toFixed(1);
    byId('mobileProfilePoints').textContent = number(p.loyalty_points).toLocaleString();
    byId('mobileProfileContact').innerHTML = [detailRow('Email',p.email),detailRow('Mobile',p.mobile),detailRow('Date of birth',p.date_of_birth ? Pyrk.formatDate(p.date_of_birth) : ''),detailRow('Age',p.age ? `${p.age} years` : ''),detailRow('Gender',statusText(p.gender))].join('');
    byId('mobileProfileSafety').innerHTML = [detailRow('Emergency contact',p.emergency_contact_name),detailRow('Emergency mobile',p.emergency_contact_mobile),detailRow('Medical conditions',p.medical_conditions || 'No medical notes recorded.')].join('');
    byId('mobileProfileAccount').innerHTML = [detailRow('Status',statusText(p.status)),detailRow('Profile editing',canEditOwnProfile?'Allowed':'Disabled by administrator'),detailRow('Photo consent',number(p.photo_consent)===1?'Approved':'Not approved'),detailRow('Member since',p.created_at?Pyrk.formatDate(p.created_at):'')].join('');
    const groups = data.groups || [];
    byId('mobileProfileGroups').innerHTML = groups.length ? groups.map(g=>`<span>👥 ${esc(g.group_name || 'Group')}</span>`).join('') : '<small>No groups assigned.</small>';
    const waivers = data.waivers || [];
    byId('mobileProfileWaivers').innerHTML = waivers.length ? waivers.map(w=>`<article class="mobile-history-card"><div class="mobile-history-head"><h3>${esc(w.walk_title || 'Walk waiver')}</h3><time>${esc(Pyrk.formatDate(w.signed_at))}</time></div><p class="mobile-card-copy">${esc(w.waiver_title || 'Waiver')}${w.waiver_version ? ' · v'+esc(w.waiver_version) : ''}</p></article>`).join('') : emptyCard('No signed waivers', 'Signed walk waivers will appear here.');

    const photos = data.photos || [];
    byId('mobileProfilePhotos').innerHTML = photos.length ? photos.map(photo => {
      const thumb = mediaUrl(photo.thumbnail_path || photo.file_path);
      const full = mediaUrl(photo.file_path || photo.thumbnail_path);
      return `<button class="mobile-photo-tile" type="button" data-photo-src="${esc(full)}" data-photo-title="${esc(photo.title || photo.walk_title || 'Photo')}" data-photo-meta="${esc((photo.walk_title || '') + (photo.uploaded_at ? ' · ' + Pyrk.formatDate(photo.uploaded_at) : ''))}"><img src="${esc(thumb)}" alt="${esc(photo.title || 'Walk photo')}" loading="lazy"><span>${esc(photo.title || photo.walk_title || 'Photo')}</span></button>`;
    }).join('') : emptyCard('No photos uploaded yet', 'Photos you upload during walks will appear here.');
    fillProfileForm(p);
    setUnread(data.unread_count || 0);
  }

  async function loadProfile() {
    const res = await Pyrk.get('mobile_member.php', {action:'profile'});
    if (!res.ok) { byId('mobileProfilePhotos').innerHTML = errorCard(res.message); return; }
    renderProfile(res.data || {});
  }

  function openProfileEdit() {
    if (!canEditOwnProfile) {
      alert('Profile editing has been disabled for your account by an administrator.');
      return;
    }
    if (profileCache) fillProfileForm(profileCache);
    byId('mobileProfileEditSheet').hidden = false;
    document.body.style.overflow = 'hidden';
  }

  function closeProfileEdit() {
    byId('mobileProfileEditSheet').hidden = true;
    document.body.style.overflow = '';
  }

  async function saveProfile(event) {
    event.preventDefault();
    if (!canEditOwnProfile) {
      const blockedMessage = byId('mobileProfileEditMessage');
      if (blockedMessage) {
        blockedMessage.textContent = 'Profile editing is disabled for your account.';
        blockedMessage.className = 'mobile-form-message is-bad';
      }
      return;
    }
    const form = event.currentTarget;
    const names = `${byId('mobileProfileFirstName').value.trim()} ${byId('mobileProfileLastName').value.trim()}`.trim();
    byId('mobileProfileFullName').value = names;
    const fd = new FormData(form);
    fd.set('action','update_profile');
    const message = byId('mobileProfileEditMessage');
    message.textContent = 'Saving…';
    message.className = 'mobile-form-message';
    const res = await Pyrk.postForm('account.php', fd, {timeoutMs:30000});
    message.textContent = res.message || (res.ok ? 'Profile saved.' : 'Could not save profile.');
    message.className = 'mobile-form-message ' + (res.ok ? 'is-good' : 'is-bad');
    if (res.ok) {
      await loadProfile();
      setTimeout(closeProfileEdit, 450);
    }
  }

  function bindCommon() {
    document.querySelectorAll('[data-mobile-refresh]').forEach(btn => btn.addEventListener('click', () => location.reload()));
    document.addEventListener('click', event => {
      const reward = event.target.closest('[data-reward-id]');
      if (reward) claimReward(reward);
      const photo = event.target.closest('[data-photo-src]');
      if (photo) openPhoto(photo.dataset.photoSrc, photo.dataset.photoTitle, photo.dataset.photoMeta);
      if (event.target.closest('[data-photo-viewer-close]')) closePhoto();
      if (event.target.closest('[data-mobile-sheet-close]')) closeProfileEdit();
    });
  }

  async function init() {
    bindCommon();
    if (page === 'home') await loadHome();
    else if (page === 'walks') { await Promise.all([loadWalks(), loadUnread()]); }
    else if (page === 'history') await loadHistory();
    else if (page === 'activity') await loadActivity();
    else if (page === 'rewards') await loadRewards();
    else if (page === 'profile') {
      byId('mobileOpenProfileEdit')?.addEventListener('click', openProfileEdit);
      byId('mobileProfileEditForm')?.addEventListener('submit', saveProfile);
      byId('mobileProfilePhotoInput')?.addEventListener('change', event => {
        const file = event.target.files?.[0];
        if (!file) return;
        const src = URL.createObjectURL(file);
        byId('mobileProfileEditPreview').innerHTML = `<img src="${esc(src)}" alt="Preview">`;
      });
      byId('mobileProfileAvatarButton')?.addEventListener('click', () => {
        const src = mediaUrl(profileCache?.profile_photo_path || '');
        if (src) openPhoto(src, profileCache?.full_name || 'Profile photo', 'Profile photo');
      });
      await loadProfile();
    }
  }

  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
  else init();
})();
