import './bootstrap';

import Alpine from 'alpinejs';

window.Alpine = Alpine;

Alpine.start();

// PWA: register service worker (production + local).
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js').catch(() => {
      // Non-fatal: app should still work without SW.
    });
  });
}

async function ensurePushSubscription() {
  const vapid =
    document.querySelector('meta[name="vapid-public-key"]')?.getAttribute('content') ||
    import.meta.env.VITE_VAPID_PUBLIC_KEY;
  if (!vapid) return;
  if (!('serviceWorker' in navigator) || !('PushManager' in window)) return;

  const reg = await navigator.serviceWorker.ready;
  const permission = await Notification.requestPermission();
  if (permission !== 'granted') return;

  const existing = await reg.pushManager.getSubscription();
  const sub = existing || await reg.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: urlBase64ToUint8Array(vapid),
  });

  await window.axios.post('/push/subscribe', sub);
}

async function disablePushSubscription() {
  if (!('serviceWorker' in navigator) || !('PushManager' in window)) return;
  const reg = await navigator.serviceWorker.ready;
  const existing = await reg.pushManager.getSubscription();
  if (!existing) return;
  try {
    await window.axios.post('/push/unsubscribe', { endpoint: existing.endpoint });
  } catch {
    // ignore
  }
  try {
    await existing.unsubscribe();
  } catch {
    // ignore
  }
}

async function getPushStatus() {
  if (!('serviceWorker' in navigator) || !('PushManager' in window)) return { supported: false };
  const perm = typeof Notification !== 'undefined' ? Notification.permission : 'default';
  const reg = await navigator.serviceWorker.ready;
  const sub = await reg.pushManager.getSubscription();
  return { supported: true, permission: perm, subscribed: !!sub };
}

function urlBase64ToUint8Array(base64String) {
  const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
  const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
  const rawData = window.atob(base64);
  const outputArray = new Uint8Array(rawData.length);
  for (let i = 0; i < rawData.length; ++i) outputArray[i] = rawData.charCodeAt(i);
  return outputArray;
}

// Lazy-init push subscription when user is logged in.
window.addEventListener('load', () => {
  if (document.querySelector('meta[name="csrf-token"]')) {
    ensurePushSubscription().catch(() => {});
  }
});

// Expose for UI buttons (Account screen + prompt).
window.WeSharePush = {
  enable: () => ensurePushSubscription(),
  disable: () => disablePushSubscription(),
  status: () => getPushStatus(),
};

// Reliable back behavior (works even after auto-reloads).
window.WeShareNav = {
  back: (fallback = '/') => {
    try {
      const ref = document.referrer || '';
      const sameOrigin = ref && new URL(ref).origin === window.location.origin;
      if (sameOrigin) {
        window.location.href = ref;
        return;
      }
    } catch {}
    if (window.history.length > 1) {
      window.history.back();
      return;
    }
    window.location.href = fallback;
  },
};

function initSelectableMemberRows(root = document) {
  root.querySelectorAll('[data-member-row]').forEach((row) => {
    if (row.dataset.memberRowInit === '1') return;
    row.dataset.memberRowInit = '1';

    const cb = row.querySelector('input[data-member]');
    const hint = row.querySelector('[data-member-hint]');
    if (!cb) return;

    const update = () => {
      const on = !!cb.checked;
      row.classList.toggle('ring-2', on);
      row.classList.toggle('ring-primary/25', on);
      row.classList.toggle('bg-primary/5', on);
      row.setAttribute('aria-checked', on ? 'true' : 'false');
      if (hint) {
        const addedLabel = hint.dataset.addedLabel || 'Added';
        const idleLabel = hint.dataset.idleLabel || 'Tap to add';
        hint.textContent = on ? addedLabel : idleLabel;
        hint.classList.toggle('bg-primary/10', on);
        hint.classList.toggle('text-primary', on);
        hint.classList.toggle('text-muted-foreground', !on);
      }
    };

    row.addEventListener('click', (event) => {
      const target = event.target;
      if (target instanceof HTMLElement && target.closest('a, button, input, select, textarea')) {
        return;
      }

      event.preventDefault();
      cb.checked = !cb.checked;
      cb.dispatchEvent(new Event('change', { bubbles: true }));
    });

    row.addEventListener('keydown', (event) => {
      if (event.key !== 'Enter' && event.key !== ' ') return;
      event.preventDefault();
      cb.checked = !cb.checked;
      cb.dispatchEvent(new Event('change', { bubbles: true }));
    });

    cb.addEventListener('change', update);
    update();
  });
}

window.WeShareMembers = {
  initRows: initSelectableMemberRows,
};

function mountNotificationsPrompt() {
  const csrf = document.querySelector('meta[name="csrf-token"]');
  if (!csrf) return;
  if (!('Notification' in window)) return;
  if (Notification.permission !== 'default') return;
  if (localStorage.getItem('weshare_push_prompt_dismissed') === '1') return;

  const wrap = document.createElement('div');
  wrap.id = 'weshare-push-prompt';
  wrap.className =
    'fixed inset-0 z-[80] flex items-end md:items-center justify-center p-4 bg-black/40 backdrop-blur-sm';
  wrap.innerHTML = `
    <div class="w-full max-w-md apple-card p-5 md:p-6">
      <div class="flex items-center gap-3">
        <div class="w-10 h-10 rounded-2xl bg-primary/10 flex items-center justify-center text-primary font-bold">🔔</div>
        <div class="min-w-0">
          <p class="text-[16px] font-semibold text-foreground">Enable notifications?</p>
          <p class="text-[13px] text-muted-foreground mt-0.5">Get alerts when someone adds expenses, items, or settles up.</p>
        </div>
      </div>
      <div class="mt-5 flex gap-2">
        <button type="button" data-enable class="flex-1 py-3 rounded-2xl bg-primary text-primary-foreground text-[14px] font-semibold">Enable</button>
        <button type="button" data-later class="flex-1 py-3 rounded-2xl bg-secondary text-foreground text-[14px] font-semibold">Not now</button>
      </div>
    </div>
  `;

  function close(dismiss = false) {
    if (dismiss) localStorage.setItem('weshare_push_prompt_dismissed', '1');
    wrap.remove();
  }

  wrap.addEventListener('click', (e) => {
    if (e.target === wrap) close(true);
  });
  wrap.querySelector('[data-later]')?.addEventListener('click', () => close(true));
  wrap.querySelector('[data-enable]')?.addEventListener('click', async () => {
    try {
      await ensurePushSubscription();
    } finally {
      close(true);
    }
  });

  document.body.appendChild(wrap);
}

window.addEventListener('load', () => {
  mountNotificationsPrompt();
  initSelectableMemberRows();
});

function initCollectionFilters(root = document) {
  root.querySelectorAll('[data-collection-root]').forEach((collection) => {
    if (collection.dataset.collectionInit === '1') return;
    collection.dataset.collectionInit = '1';

    const input = collection.querySelector('[data-collection-search]');
    const chips = Array.from(collection.querySelectorAll('[data-collection-chip]'));
    const items = Array.from(collection.querySelectorAll('[data-collection-item]'));
    const sections = Array.from(collection.querySelectorAll('[data-collection-section]'));
    const emptyState = collection.querySelector('[data-collection-empty]');
    const noResults = collection.querySelector('[data-collection-no-results]');

    const apply = () => {
      const query = (input?.value || '').trim().toLowerCase();
      const activeChip = chips.find((chip) => chip.dataset.active === 'true');
      const filter = activeChip?.dataset.collectionChip || 'all';

      items.forEach((item) => {
        const text = (item.dataset.collectionText || '').toLowerCase();
        const groups = (item.dataset.collectionFilters || '').split(' ').filter(Boolean);
        const matchesText = !query || text.includes(query);
        const matchesFilter = filter === 'all' || groups.includes(filter);
        item.classList.toggle('hidden', !(matchesText && matchesFilter));
      });

      sections.forEach((section) => {
        const visible = Array.from(section.querySelectorAll('[data-collection-item]')).some((item) => !item.classList.contains('hidden'));
        section.classList.toggle('hidden', !visible);
      });

      if (emptyState) {
        const hasItems = items.length > 0;
        emptyState.classList.toggle('hidden', hasItems);
      }

      if (noResults) {
        const hasVisibleItems = items.some((item) => !item.classList.contains('hidden'));
        noResults.classList.toggle('hidden', !items.length || hasVisibleItems);
      }
    };

    chips.forEach((chip) => {
      chip.addEventListener('click', () => {
        chips.forEach((other) => {
          const active = other === chip;
          other.dataset.active = active ? 'true' : 'false';
          other.classList.toggle('bg-primary', active);
          other.classList.toggle('text-primary-foreground', active);
          other.classList.toggle('shadow-sm', active);
          other.classList.toggle('bg-secondary/80', !active);
          other.classList.toggle('text-foreground', !active);
        });
        apply();
      });
    });

    input?.addEventListener('input', apply);
    apply();
  });
}

window.WeShareCollections = {
  init: initCollectionFilters,
};

// "Realtime" without websockets: smart polling for space updates.
function startLivePolling() {
  const csrf = document.querySelector('meta[name="csrf-token"]');
  if (!csrf) return; // guests

  let lastVersion = null;
  let inflight = false;

  async function tick() {
    if (inflight) return;
    if (document.visibilityState === 'hidden') return;

    inflight = true;
    try {
      const res = await window.axios.get('/live/poll', { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
      const v = Number(res?.data?.version ?? 0);
      if (lastVersion === null) {
        lastVersion = v;
        return;
      }
      if (v > lastVersion) {
        // New changes in this space; simplest + safest is a full reload.
        window.location.reload();
      }
    } catch {
      // ignore transient failures
    } finally {
      inflight = false;
    }
  }

  // Start after page load, then every 4s.
  tick();
  window.setInterval(tick, 4000);
}

window.addEventListener('load', () => {
  startLivePolling();
  initCollectionFilters();
});
