/* NRI Property Guard — Property Executive web dashboard logic (v1)
   Covers: Today's/Upcoming/All assigned visits, a visit detail screen with
   Mark Reached / Start Visit (browser Geolocation), Google Maps navigation,
   photo/video upload with GPS captured as metadata (the mobile app's baked-in
   map-thumbnail + address stamp on the image itself is a documented v2
   follow-up — GPS is still captured and stored here, just shown alongside the
   media rather than rendered onto it), and final submission via the same
   executive_submit_inspection() RPC the mobile app uses. */
(function () {
  var sb = window.sbClient;
  var N = window.NRIPG;

  var CHECKLIST_ITEMS = [
    'Exterior condition checked', 'Interior condition checked',
    'No unauthorized occupants', 'Utilities (power/water) functional',
    'Doors, windows and locks intact', 'Compound/boundary secure'
  ];

  var State = {
    session: null, userId: null, executiveId: null,
    assignments: [], currentAssignment: null, currentView: 'today',
    capturedLat: null, capturedLng: null, capturedAccuracy: null
  };

  /* ============================== BOOT ============================== */
  async function boot() {
    var { data } = await sb.auth.getSession();
    if (!data || !data.session) { location.href = 'index.html'; return; }
    State.session = data.session; State.userId = data.session.user.id;

    var roleRes = await sb.from('users').select('role').eq('id', State.userId).maybeSingle();
    var role = (roleRes.data && roleRes.data.role) || 'customer';
    if (role !== 'property_executive') { location.href = 'index.html'; return; }

    var execRes = await sb.from('property_executives').select('id').eq('user_id', State.userId).maybeSingle();
    State.executiveId = execRes.data ? execRes.data.id : null;

    var userRes = await sb.from('users').select('*').eq('id', State.userId).maybeSingle();
    document.getElementById('avatarChip').textContent = N.initials((userRes.data && userRes.data.name) || State.session.user.email);

    document.getElementById('loadingGate').style.display = 'none';
    document.getElementById('appShell').style.display = '';

    bindNav();

    await loadAssignments();
    // loadAssignments() already re-renders all three list tabs unconditionally,
    // so the only extra thing a silent refresh needs to do is re-render the
    // currently open Visit Detail (if any) with the freshly reloaded data.
    N.startAutoRefresh(function () { refreshCurrentView(); }, 30000);
  }

  async function refreshCurrentView() {
    var onDetail = document.getElementById('view-detail').classList.contains('active');
    var openId = State.currentAssignment ? State.currentAssignment.id : null;
    await loadAssignments();
    if (onDetail && openId) {
      var updated = State.assignments.find(function (a) { return a.id === openId; });
      if (updated) { State.currentAssignment = updated; renderDetail(); }
    }
  }

  /* ============================== NAV ============================== */
  function bindNav() {
    document.querySelectorAll('.side-nav a[data-view]').forEach(function (a) {
      a.addEventListener('click', function () { switchView(a.dataset.view); });
    });
    document.getElementById('menuBtn').addEventListener('click', function () {
      document.getElementById('sidebar').classList.toggle('open');
    });
    document.getElementById('logoutBtn').addEventListener('click', async function () {
      await sb.auth.signOut();
      location.href = 'index.html';
    });
    document.getElementById('backBtn').addEventListener('click', function () { switchView(State.currentView === 'detail' ? 'today' : State.currentView); });
    document.querySelectorAll('[data-close-modal]').forEach(function (btn) {
      btn.addEventListener('click', function () { closeModal(btn.dataset.closeModal); });
    });
    document.querySelectorAll('[data-maximize-modal]').forEach(function (btn) {
      btn.addEventListener('click', function () {
        var backdrop = document.getElementById(btn.dataset.maximizeModal);
        N.toggleModalMaximize(backdrop.querySelector('.lightbox-modal') || backdrop);
      });
    });
    document.querySelectorAll('.modal-backdrop').forEach(function (backdrop) {
      backdrop.addEventListener('click', function (e) { if (e.target === backdrop) closeModal(backdrop.id); });
    });
  }
  function openModal(id) { document.getElementById(id).classList.add('open'); }
  function closeModal(id) {
    var el = document.getElementById(id);
    el.classList.remove('open');
    N.resetModalMaximize(el.querySelector('.lightbox-modal') || el);
  }

  var TITLES = { today: "Today's Visits", upcoming: 'Upcoming Visits', all: 'All Assigned Sites', detail: 'Visit Detail' };

  function switchView(name) {
    document.querySelectorAll('.view').forEach(function (v) { v.classList.remove('active'); });
    var el = document.getElementById('view-' + name);
    if (el) el.classList.add('active');
    document.querySelectorAll('.side-nav a[data-view]').forEach(function (a) { a.classList.toggle('active', a.dataset.view === name); });
    document.getElementById('viewTitle').textContent = TITLES[name] || name;
    document.getElementById('sidebar').classList.remove('open');
    if (name !== 'detail') State.currentView = name;
  }

  function emptyState(icon, msg) { return '<div class="empty-state"><div class="ic">' + icon + '</div><p class="mb-0">' + msg + '</p></div>'; }

  /* ============================== ASSIGNMENTS ============================== */
  async function loadAssignments() {
    var res = await sb.from('visit_assignments')
      .select('*, site_visits(*, properties(property_name, address, city, state, google_map_url, latitude, longitude), customer:customer_id(user_id))')
      .neq('status', 'cancelled')
      .order('created_at', { ascending: false });
    if (res.error) { N.toast(res.error.message || 'Could not load your visits.', 'error'); State.assignments = []; }
    else State.assignments = res.data || [];

    var userIds = State.assignments.filter(function (a) { return a.site_visits && a.site_visits.customer && a.site_visits.customer.user_id; }).map(function (a) { return a.site_visits.customer.user_id; });
    var names = {};
    if (userIds.length) {
      var uRes = await sb.from('users').select('id, name').in('id', userIds);
      (uRes.data || []).forEach(function (u) { names[u.id] = u.name; });
    }
    State.assignments.forEach(function (a) {
      a._ownerName = (a.site_visits && a.site_visits.customer && a.site_visits.customer.user_id) ? (names[a.site_visits.customer.user_id] || '—') : '—';
    });

    renderLists();
  }

  function renderLists() {
    var today = new Date(); today.setHours(0, 0, 0, 0);
    var tomorrow = new Date(today); tomorrow.setDate(tomorrow.getDate() + 1);

    var todayList = State.assignments.filter(function (a) {
      if (!a.site_visits) return false;
      var d = new Date(a.site_visits.scheduled_date);
      return d >= today && d < tomorrow;
    });
    var upcomingList = State.assignments.filter(function (a) {
      if (!a.site_visits) return false;
      return new Date(a.site_visits.scheduled_date) >= tomorrow && ['assigned', 'reached', 'in_progress'].indexOf(a.status) !== -1;
    });

    document.getElementById('todayList').innerHTML = renderAssignmentCards(todayList, 'No visits scheduled for today.');
    document.getElementById('upcomingList').innerHTML = renderAssignmentCards(upcomingList, 'No upcoming visits scheduled.');
    document.getElementById('allList').innerHTML = renderAssignmentCards(State.assignments, 'No sites assigned to you yet.');
  }

  function renderAssignmentCards(list, emptyMsg) {
    if (!list.length) return emptyState('📅', emptyMsg);
    return list.map(function (a) {
      var p = a.site_visits && a.site_visits.properties;
      return '<div class="prop-card" data-assignment="' + a.id + '">' +
        '<div class="row1"><b>' + N.escapeHtml((p && p.property_name) || 'Property') + '</b><span class="status-chip status-' + a.status + '">' + N.statusLabel(a.status) + '</span></div>' +
        '<div class="meta">Owner: ' + N.escapeHtml(a._ownerName) + ' · ' + N.fmtDateTime(a.site_visits.scheduled_date) + '</div>' +
        '<div class="meta">' + N.escapeHtml((p && p.city) || '') + ', ' + N.escapeHtml((p && p.state) || '') + '</div></div>';
    }).join('');
  }

  // Delegate clicks (cards are re-rendered on every load/switch)
  document.addEventListener('click', function (e) {
    var card = e.target.closest && e.target.closest('[data-assignment]');
    if (card) openDetail(card.dataset.assignment);
  });

  /* ============================== VISIT DETAIL ============================== */
  function openDetail(assignmentId) {
    State.currentAssignment = State.assignments.find(function (a) { return a.id === assignmentId; });
    if (!State.currentAssignment) return;
    switchView('detail');
    renderDetail();
  }

  function renderDetail() {
    var a = State.currentAssignment;
    var v = a.site_visits;
    var p = v.properties;
    var mapUrl = p.google_map_url || (p.latitude ? ('https://www.google.com/maps/search/?api=1&query=' + p.latitude + ',' + p.longitude) : null);
    var body = document.getElementById('detailBody');

    var actionsHtml = '';
    if (a.status === 'assigned') {
      actionsHtml = '<button class="btn btn-primary btn-block" id="markReachedBtn">📍 Mark Reached</button>';
    } else if (a.status === 'reached') {
      actionsHtml = '<button class="btn btn-primary btn-block" id="startVisitBtn">▶️ Start Visit</button>';
    } else if (a.status === 'in_progress') {
      actionsHtml = renderSubmissionForm();
    } else {
      actionsHtml = '<p class="help-note">This visit is ' + N.statusLabel(a.status).toLowerCase() + ' — no further action needed here.</p>';
    }

    body.innerHTML =
      '<div class="card">' +
        '<h2 style="margin-bottom:6px;">' + N.escapeHtml(p.property_name) + '</h2>' +
        '<p>' + N.escapeHtml(p.address) + ', ' + N.escapeHtml(p.city) + ', ' + N.escapeHtml(p.state) + '</p>' +
        '<div class="chip-row"><span class="mini-chip">Owner: ' + N.escapeHtml(a._ownerName) + '</span><span class="mini-chip">Scheduled: ' + N.fmtDateTime(v.scheduled_date) + '</span><span class="status-chip status-' + a.status + '">' + N.statusLabel(a.status) + '</span></div>' +
        (mapUrl ? '<p style="margin-top:12px;"><a href="' + N.escapeHtml(mapUrl) + '" target="_blank" rel="noopener">🧭 Navigate with Google Maps →</a></p>' : '') +
      '</div>' +
      '<div class="card" id="actionCard">' + actionsHtml + '</div>' +
      (a.status === 'in_progress' ? '<div class="card"><div class="card-head"><h3>Captured Media</h3></div><div id="mediaGrid"><div class="skel" style="height:60px;"></div></div></div>' : '');

    if (a.status === 'assigned') {
      document.getElementById('markReachedBtn').addEventListener('click', markReached);
    } else if (a.status === 'reached') {
      document.getElementById('startVisitBtn').addEventListener('click', startVisit);
    } else if (a.status === 'in_progress') {
      bindSubmissionForm();
      loadMedia();
    }
  }

  function captureLocation() {
    return new Promise(function (resolve) {
      if (!navigator.geolocation) { resolve(null); return; }
      navigator.geolocation.getCurrentPosition(function (pos) {
        resolve({ lat: pos.coords.latitude, lng: pos.coords.longitude, accuracy: pos.coords.accuracy });
      }, function () { resolve(null); }, { timeout: 8000 });
    });
  }

  async function markReached() {
    var btn = document.getElementById('markReachedBtn');
    btn.disabled = true; btn.innerHTML = '<span class="loading-spin"></span> Capturing location…';
    var loc = await captureLocation();
    var patch = { status: 'reached', reached_at: new Date().toISOString() };
    if (loc) { patch.gps_lat = loc.lat; patch.gps_lng = loc.lng; patch.gps_accuracy_m = loc.accuracy; }
    var res = await sb.from('visit_assignments').update(patch).eq('id', State.currentAssignment.id);
    if (res.error) { N.toast(res.error.message, 'error'); btn.disabled = false; btn.textContent = '📍 Mark Reached'; return; }
    N.toast('Marked as reached.', 'success');
    State.currentAssignment.status = 'reached';
    await loadAssignments();
    State.currentAssignment = State.assignments.find(function (a) { return a.id === State.currentAssignment.id; });
    renderDetail();
  }

  async function startVisit() {
    var btn = document.getElementById('startVisitBtn');
    btn.disabled = true; btn.innerHTML = '<span class="loading-spin"></span> Starting…';
    var res = await sb.from('visit_assignments').update({ status: 'in_progress', started_at: new Date().toISOString() }).eq('id', State.currentAssignment.id);
    if (res.error) { N.toast(res.error.message, 'error'); btn.disabled = false; btn.textContent = '▶️ Start Visit'; return; }
    N.toast('Visit started.', 'success');
    await loadAssignments();
    State.currentAssignment = State.assignments.find(function (a) { return a.id === State.currentAssignment.id; });
    renderDetail();
  }

  /* ============================== MEDIA (PHOTOS / VIDEOS) ============================== */
  async function loadMedia() {
    var siteVisitId = State.currentAssignment.site_visits.id;
    var photosRes = await sb.from('visit_photos').select('*').eq('site_visit_id', siteVisitId).order('captured_at', { ascending: false });
    var videosRes = await sb.from('visit_videos').select('*').eq('site_visit_id', siteVisitId).order('captured_at', { ascending: false });
    var photos = photosRes.data || [], videos = videosRes.data || [];
    var el = document.getElementById('mediaGrid');
    if (!photos.length && !videos.length) { el.innerHTML = emptyState('📸', 'No photos or videos captured yet.'); return; }
    el.innerHTML = '<div class="media-grid">' +
      photos.map(mediaTile.bind(null, 'property-images', 'photo')).join('') +
      videos.map(mediaTile.bind(null, 'property-videos', 'video')).join('') +
      '</div>';
    bindMediaTiles(el);
  }

  // GPS and timestamp are still captured and stored with every photo/video
  // (captured_at/gps_lat/gps_lng on the row, still mandatory — see
  // uploadFiles() below) for the tamper-evident audit trail, but are not
  // rendered as an overlay on the media itself (Phase 8, per explicit request).
  function mediaTile(bucket, kind, m) {
    return '<div class="media-tile" data-media-bucket="' + bucket + '" data-media-path="' + N.escapeHtml(m.storage_path) + '" data-media-kind="' + kind + '">' +
      (kind === 'photo' ? '🖼️' : '🎬') + '</div>';
  }

  function bindMediaTiles(scope) {
    scope.querySelectorAll('.media-tile').forEach(function (tile) {
      tile.addEventListener('click', async function () {
        var bucket = tile.dataset.mediaBucket, path = tile.dataset.mediaPath, kind = tile.dataset.mediaKind;
        var signed = await sb.storage.from(bucket).createSignedUrl(path, 600);
        if (signed.error || !signed.data) { N.toast('Could not open this file.', 'error'); return; }
        var url = signed.data.signedUrl;
        document.getElementById('lightboxBody').innerHTML = '<div class="lightbox-media-wrap">' + (kind === 'photo'
          ? '<img src="' + url + '">'
          : '<video src="' + url + '" controls autoplay></video>') + '</div>';
        openModal('lightboxModal');
      });
    });
  }

  async function uploadFiles(files, kind, inputEl) {
    var a = State.currentAssignment;
    var v = a.site_visits;
    N.toast('Getting your location…', 'info');
    var loc = await captureLocation();
    // GPS is now mandatory on every photo/video, not best-effort: an inspection
    // photo with no location attached is exactly the "no timestamp/geo location"
    // gap that was reported, so an upload with no GPS fix is rejected outright
    // rather than silently saved without it. The file input is reset so the
    // same file(s) can be re-selected once location access is sorted out.
    if (!loc) {
      N.toast('Location is required for every photo and video. Please allow location access (or move somewhere with a GPS signal) and try again.', 'error');
      if (inputEl) inputEl.value = '';
      return;
    }
    var table = kind === 'photo' ? 'visit_photos' : 'visit_videos';
    var bucket = kind === 'photo' ? 'property-images' : 'property-videos';
    for (var i = 0; i < files.length; i++) {
      var f = files[i];
      var path = 'inspection/' + v.id + '/' + Date.now() + '_' + i + '_' + f.name.replace(/[^a-zA-Z0-9._-]/g, '_');
      var up = await sb.storage.from(bucket).upload(path, f);
      if (up.error) { N.toast('Upload failed: ' + up.error.message, 'error'); continue; }
      var row = {
        site_visit_id: v.id, property_id: v.property_id, executive_id: State.executiveId, manager_id: v.manager_id,
        media_source: 'inspection', storage_path: path, captured_at: new Date().toISOString(), file_size_bytes: f.size,
        gps_lat: loc.lat, gps_lng: loc.lng, gps_accuracy_m: loc.accuracy
      };
      var ins = await sb.from(table).insert(row);
      if (ins.error) N.toast('Could not save ' + f.name + ': ' + ins.error.message, 'error');
    }
    N.toast('Upload complete.', 'success');
    if (inputEl) inputEl.value = '';
    loadMedia();
  }

  /* ============================== SUBMISSION FORM ============================== */
  function renderSubmissionForm() {
    return '<h3>Submit Inspection</h3>' +
      '<div class="field"><label>Add Photos</label><input type="file" id="photoInput" accept="image/*" multiple capture="environment"></div>' +
      '<div class="field"><label>Add Videos</label><input type="file" id="videoInput" accept="video/*" multiple capture="environment"></div>' +
      '<div class="field"><label>Property condition</label><select id="conditionSelect"><option value="healthy">Healthy</option><option value="needsAttention">Needs Attention</option><option value="underMaintenance">Under Maintenance</option><option value="emergency">Emergency</option></select></div>' +
      '<div class="field"><label>Checklist</label>' + CHECKLIST_ITEMS.map(function (item, i) { return '<label style="display:flex;align-items:center;gap:8px;font-weight:400;margin-bottom:6px;"><input type="checkbox" class="checklist-item" data-item="' + N.escapeHtml(item) + '"> ' + N.escapeHtml(item) + '</label>'; }).join('') + '</div>' +
      '<div class="field"><label>Notes</label><textarea id="notesInput" placeholder="Anything the Manager should know"></textarea></div>' +
      '<div class="field"><label>Observations (optional)</label><textarea id="observationsInput"></textarea></div>' +
      '<div class="alert" id="submitAlert"></div>' +
      '<button class="btn btn-primary btn-block" id="submitInspectionBtn">✅ Submit Inspection</button>';
  }

  function bindSubmissionForm() {
    document.getElementById('photoInput').addEventListener('change', function (e) { if (e.target.files.length) uploadFiles(e.target.files, 'photo', e.target); });
    document.getElementById('videoInput').addEventListener('change', function (e) { if (e.target.files.length) uploadFiles(e.target.files, 'video', e.target); });
    document.getElementById('submitInspectionBtn').addEventListener('click', submitInspection);
  }

  async function submitInspection() {
    var btn = document.getElementById('submitInspectionBtn');
    var alertEl = document.getElementById('submitAlert');
    alertEl.className = 'alert';
    btn.disabled = true; btn.innerHTML = '<span class="loading-spin"></span> Submitting…';
    try {
      var loc = await captureLocation();
      var checklist = Array.prototype.slice.call(document.querySelectorAll('.checklist-item')).map(function (cb) { return { item: cb.dataset.item, checked: cb.checked }; });
      var a = State.currentAssignment;
      var startedAt = a.started_at ? new Date(a.started_at) : new Date();
      var durationMin = Math.max(1, Math.round((Date.now() - startedAt.getTime()) / 60000));

      var res = await sb.rpc('executive_submit_inspection', {
        p_assignment_id: a.id,
        p_notes: document.getElementById('notesInput').value || '',
        p_observations: document.getElementById('observationsInput').value || '',
        p_property_condition: document.getElementById('conditionSelect').value,
        p_checklist: checklist,
        p_gps_lat: loc ? loc.lat : null,
        p_gps_lng: loc ? loc.lng : null,
        p_gps_accuracy: loc ? loc.accuracy : null,
        p_visit_duration_minutes: durationMin,
        p_device_info: { platform: navigator.platform || 'web', userAgent: navigator.userAgent },
        p_network_status: navigator.onLine ? 'online' : 'offline'
      });
      if (res.error) throw res.error;

      N.toast('Inspection submitted for Manager review.', 'success');
      await loadAssignments();
      switchView('today');
    } catch (err) {
      alertEl.textContent = err.message || 'Could not submit this inspection.';
      alertEl.className = 'alert error show';
      btn.disabled = false; btn.textContent = '✅ Submit Inspection';
    }
  }

  boot();
})();
