// Push & Notification manager — Central da Vida
// Modelo: permissão de notificações + agendamento local via setTimeout.
// Não depende de backend; quando integrarmos VAPID/FCM, plugamos aqui.

(function () {
  const PREFS_KEY = 'cdv:pushPrefs:v1';
  const DEFAULT_PREFS = {
    enabled: false,           // permissão concedida e usuário aceitou
    leadMinutes: 10,          // minutos antes do horário da tarefa
    quiet: { enabled: true, start: 22, end: 7 }, // janela silenciosa
  };

  function loadPrefs() {
    try {
      const raw = localStorage.getItem(PREFS_KEY);
      if (!raw) return { ...DEFAULT_PREFS };
      const parsed = JSON.parse(raw);
      return { ...DEFAULT_PREFS, ...parsed, quiet: { ...DEFAULT_PREFS.quiet, ...(parsed.quiet || {}) } };
    } catch (e) { return { ...DEFAULT_PREFS }; }
  }

  function savePrefs(p) {
    try { localStorage.setItem(PREFS_KEY, JSON.stringify(p)); } catch (e) {}
  }

  const supported = typeof window !== 'undefined' && 'Notification' in window;

  function permission() {
    return supported ? Notification.permission : 'unsupported';
  }

  async function requestPermission() {
    if (!supported) return 'unsupported';
    if (Notification.permission === 'granted') return 'granted';
    try {
      const result = await Notification.requestPermission();
      return result;
    } catch (e) {
      return 'denied';
    }
  }

  function isQuietHour(prefs, date = new Date()) {
    if (!prefs.quiet || !prefs.quiet.enabled) return false;
    const h = date.getHours();
    const { start, end } = prefs.quiet;
    // Janela atravessa meia-noite (ex: 22-7)?
    if (start > end) return h >= start || h < end;
    return h >= start && h < end;
  }

  // Mostra agora (respeita modo silencioso)
  function showNow(title, body, options = {}) {
    if (!supported || Notification.permission !== 'granted') return false;
    const prefs = loadPrefs();
    if (isQuietHour(prefs) && !options.bypassQuiet) {
      console.log('[push] suprimida pelo modo silencioso:', title);
      return false;
    }
    try {
      new Notification(title, {
        body, icon: options.icon, badge: options.badge,
        tag: options.tag, data: options.data,
        requireInteraction: !!options.requireInteraction,
      });
      return true;
    } catch (e) {
      console.warn('[push] erro ao exibir:', e);
      return false;
    }
  }

  // Agendador local — em memória, perde ao recarregar (precisa re-agendar no boot)
  const timers = new Map(); // key → timeoutId

  function cancel(key) {
    if (timers.has(key)) {
      clearTimeout(timers.get(key));
      timers.delete(key);
    }
  }

  function cancelAll() {
    for (const id of timers.values()) clearTimeout(id);
    timers.clear();
  }

  // Agenda uma notificação para `when` (Date ou ISO string ou ms)
  function scheduleAt(key, when, title, body, options = {}) {
    if (!supported || Notification.permission !== 'granted') return { ok: false, reason: 'no-permission' };
    const ts = typeof when === 'number' ? when : new Date(when).getTime();
    const delay = ts - Date.now();
    if (delay <= 0) return { ok: false, reason: 'past' };
    if (delay > 24 * 60 * 60 * 1000) return { ok: false, reason: 'too-far' }; // máx 24h
    cancel(key);
    const id = setTimeout(() => {
      timers.delete(key);
      showNow(title, body, options);
    }, delay);
    timers.set(key, id);
    return { ok: true, in: delay };
  }

  // Re-agenda todas as tarefas pendentes de hoje (chame ao bootar e quando state muda)
  function rescheduleTasks(tasks) {
    if (!supported || Notification.permission !== 'granted') return 0;
    const prefs = loadPrefs();
    if (!prefs.enabled) return 0;
    cancelAll();

    let n = 0;
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const todayKey = today.toISOString().slice(0, 10);

    (tasks || []).forEach(t => {
      if (t.done) return;
      if (t.date !== 'hoje') return;
      if (!t.time || t.time === '—') return;
      const [hh, mm] = t.time.split(':').map(Number);
      if (Number.isNaN(hh)) return;
      const when = new Date();
      when.setHours(hh, mm || 0, 0, 0);
      // Aplica lead time (ex: 10 min antes)
      const target = when.getTime() - prefs.leadMinutes * 60 * 1000;
      if (target <= Date.now()) return; // já passou
      const ok = scheduleAt(
        'task:' + t.id + ':' + todayKey,
        target,
        t.title,
        `Daqui ${prefs.leadMinutes} min · ${t.time}`,
        { tag: 'task-' + t.id, data: { route: 'tasks', taskId: t.id } }
      );
      if (ok.ok) n++;
    });
    return n;
  }

  async function registerServiceWorker() {
    if (typeof navigator === 'undefined' || !('serviceWorker' in navigator)) return null;
    try {
      const reg = await navigator.serviceWorker.register('service-worker.js');
      return reg;
    } catch (e) {
      console.warn('[push] SW falhou:', e);
      return null;
    }
  }

  window.Push = {
    supported,
    permission,
    requestPermission,
    loadPrefs,
    savePrefs,
    isQuietHour,
    showNow,
    scheduleAt,
    cancel,
    cancelAll,
    rescheduleTasks,
    registerServiceWorker,
  };
})();
