const STORAGE_KEY = 'farmaclic.subscriptions.v1';

export function getStoredSubscriptions() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return [];
    const parsed = JSON.parse(raw);
    return Array.isArray(parsed) ? parsed : [];
  } catch {
    return [];
  }
}

function storageKey(nregistro, pharmacyId = null) {
  return pharmacyId ? `${nregistro}:${pharmacyId}` : nregistro;
}

export function isSubscribedLocally(nregistro, pharmacyId = null) {
  return getStoredSubscriptions().includes(storageKey(nregistro, pharmacyId));
}

function setStoredSubscriptions(list) {
  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify([...new Set(list)]));
  } catch {}
}

export function pushSupported() {
  return (
    typeof window !== 'undefined' &&
    'serviceWorker' in navigator &&
    'PushManager' in window &&
    'Notification' in window
  );
}

export async function getVapidPublicKey() {
  const res = await fetch('/api/notifications/vapid-public-key', { credentials: 'include' });
  if (!res.ok) {
    const message = res.status === 503
      ? 'Las notificaciones push no están configuradas en el servidor'
      : `No se pudo obtener la clave VAPID (HTTP ${res.status})`;
    throw new Error(message);
  }
  const { publicKey } = await res.json();
  if (!publicKey) throw new Error('El servidor devolvió una clave VAPID vacía');
  return publicKey;
}

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

async function getOrCreateSubscription() {
  if (!pushSupported()) {
    throw new Error('Las notificaciones push no son compatibles con este navegador');
  }
  if (window.isSecureContext === false) {
    throw new Error('Las notificaciones push requieren HTTPS (o localhost)');
  }
  const reg = await navigator.serviceWorker.ready;
  let sub = await reg.pushManager.getSubscription();
  if (sub) return sub;

  if (Notification.permission === 'denied') {
    throw new Error('Permiso de notificaciones denegado — actívalo en la configuración del navegador');
  }
  if (Notification.permission === 'default') {
    const result = await Notification.requestPermission();
    if (result !== 'granted') {
      throw new Error('Notification permission was not granted');
    }
  }
  const publicKey = await getVapidPublicKey();
  sub = await reg.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: urlBase64ToUint8Array(publicKey),
  });
  return sub;
}

export async function subscribeToPush(medicineNregistro, medicineName, pharmacyId = null) {
  const subscription = await getOrCreateSubscription();
  const res = await fetch('/api/notifications/subscribe', {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      medicine_nregistro: medicineNregistro,
      medicine_name: medicineName || null,
      subscription,
      pharmacy_id: pharmacyId || null,
    }),
  });
  if (!res.ok) {
    const detail = await res.text().catch(() => '');
    throw new Error(`Suscripción fallida (HTTP ${res.status}) ${detail}`);
  }
  setStoredSubscriptions([...getStoredSubscriptions(), storageKey(medicineNregistro, pharmacyId)]);
}

export async function unsubscribeFromPush(medicineNregistro, pharmacyId = null) {
  let endpoint = null;
  if (pushSupported()) {
    try {
      const reg = await navigator.serviceWorker.ready;
      const sub = await reg.pushManager.getSubscription();
      endpoint = sub?.endpoint || null;
    } catch {}
  }
  if (endpoint) {
    await fetch('/api/notifications/unsubscribe', {
      method: 'DELETE',
      credentials: 'include',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        medicine_nregistro: medicineNregistro,
        endpoint,
        pharmacy_id: pharmacyId || null,
      }),
    }).catch(() => {});
  }
  const key = storageKey(medicineNregistro, pharmacyId);
  setStoredSubscriptions(getStoredSubscriptions().filter(n => n !== key));
}
