// Cloud sync — espelha o state do app na tabela user_state do Supabase.
//
// Quando Supabase não está configurado, todas as funções viram no-op
// e o app continua usando apenas localStorage (sem perder funcionalidade).

(function () {
  const TABLE = 'user_state';

  function client() {
    if (window.Auth && typeof window.Auth._client === 'function') {
      return window.Auth._client();
    }
    return null;
  }

  // Carrega o state da nuvem para o user logado.
  // Retorna o objeto data se existir, ou null se for primeiro acesso.
  async function loadState(userId) {
    const c = client();
    if (!c || !userId) return null;
    const { data, error } = await c
      .from(TABLE)
      .select('data, updated_at')
      .eq('user_id', userId)
      .maybeSingle();
    if (error) {
      console.warn('[cloud-sync] loadState error:', error.message);
      return null;
    }
    return data ? { data: data.data, updatedAt: data.updated_at } : null;
  }

  // Upsert do state. Retorna { ok: boolean }.
  async function saveState(userId, stateData) {
    const c = client();
    if (!c || !userId) return { ok: false, reason: 'not-configured' };
    const { error } = await c
      .from(TABLE)
      .upsert({ user_id: userId, data: stateData }, { onConflict: 'user_id' });
    if (error) {
      console.warn('[cloud-sync] saveState error:', error.message);
      return { ok: false, reason: error.message };
    }
    return { ok: true };
  }

  // Inscreve em UPDATEs de outros dispositivos.
  // Retorna função de cleanup.
  function subscribe(userId, onChange) {
    const c = client();
    if (!c || !userId) return () => {};
    const channel = c
      .channel('user-state-' + userId)
      .on(
        'postgres_changes',
        { event: '*', schema: 'public', table: TABLE, filter: 'user_id=eq.' + userId },
        (payload) => {
          if (payload && payload.new && payload.new.data) {
            onChange(payload.new.data, payload.new.updated_at);
          }
        }
      )
      .subscribe();
    return () => {
      try { c.removeChannel(channel); } catch (e) {}
    };
  }

  // Debounced saver: chama saveState após `delay` ms de inatividade.
  function makeDebouncedSaver(delay) {
    delay = delay || 1500;
    let timer = null;
    let lastResolve = null;
    return function (userId, stateData, onStatus) {
      if (timer) clearTimeout(timer);
      onStatus && onStatus({ status: 'pending' });
      return new Promise((resolve) => {
        lastResolve = resolve;
        timer = setTimeout(async () => {
          onStatus && onStatus({ status: 'saving' });
          const res = await saveState(userId, stateData);
          onStatus && onStatus({ status: res.ok ? 'saved' : 'error', reason: res.reason });
          if (lastResolve === resolve) resolve(res);
        }, delay);
      });
    };
  }

  window.CloudSync = {
    loadState,
    saveState,
    subscribe,
    makeDebouncedSaver,
    isConfigured: () => !!client(),
  };
})();
