/* Auth (Supabase) + cliente al Worker.
   - window.sb: cliente supabase-js (auth + sesión en el navegador).
   - window.api(path, opts): fetch al Worker con el JWT del usuario adjunto.
   - window.useSession(): hook con la sesión actual. */
(() => {
  const cfg = window.SUPABASE_CONFIG || {};
  // supabase-js UMD expone window.supabase.createClient
  const sb = window.supabase.createClient(cfg.url, cfg.anonKey, {
    // PKCE: el enlace del correo trae un ?code= de un solo uso, no el access_token.
    // El token nunca aparece en la URL. supabase-js canjea el code y limpia la URL.
    auth: { persistSession: true, autoRefreshToken: true, detectSessionInUrl: true, flowType: 'pkce' },
  });
  window.sb = sb;

  // SSO entre apps de la suite (mismo proyecto Supabase). Si llegamos con la
  // sesión en el fragmento (#sso_at&sso_rt), la instalamos y limpiamos la URL al
  // toque (el fragmento no viaja al servidor). Es la sesión del mismo usuario.
  (function ssoDesdeHash() {
    try {
      const h = new URLSearchParams((location.hash || '').replace(/^#/, ''));
      const at = h.get('sso_at'), rt = h.get('sso_rt');
      if (at && rt) {
        history.replaceState(null, '', location.pathname + location.search);
        // Guardamos la promesa: useSession la espera para no parpadear el login
        // mientras se instala la sesión traída de otra app.
        window.__ssoReady = sb.auth.setSession({ access_token: at, refresh_token: rt }).catch(() => {});
      }
    } catch (e) { /* noop */ }
  })();

  // Ir a otra app de la suite llevando la sesión actual (por el fragmento).
  // La navegación se envuelve en la transición de salida (cortina de tiles); si
  // no está cargada, navega directo.
  const irCon = (href) => { if (window.transicionSalida) window.transicionSalida(() => { location.href = href; }); else location.href = href; };
  window.irApp = async (baseUrl) => {
    try {
      const { data } = await sb.auth.getSession();
      const s = data.session;
      if (s && s.access_token && s.refresh_token) {
        const u = new URL(baseUrl);
        u.hash = 'sso_at=' + encodeURIComponent(s.access_token) + '&sso_rt=' + encodeURIComponent(s.refresh_token);
        irCon(u.toString());
        return;
      }
    } catch (e) { /* noop */ }
    irCon(baseUrl);
  };

  async function api(path, opts = {}) {
    const { data } = await sb.auth.getSession();
    const token = data.session?.access_token;
    const headers = { 'Content-Type': 'application/json', ...(opts.headers || {}) };
    if (token) headers['Authorization'] = 'Bearer ' + token;
    const res = await fetch((cfg.apiBase || '') + path, { ...opts, headers });
    const txt = await res.text();
    let body = null;
    try { body = txt ? JSON.parse(txt) : null; } catch { body = txt; }
    if (!res.ok) {
      const msg = (body && body.error) ? (body.error + (body.detalle ? ' — ' + body.detalle : '')) : ('HTTP ' + res.status);
      const err = new Error(msg); err.status = res.status; err.body = body;
      throw err;
    }
    return body;
  }
  window.api = api;

  // Subida de archivos: manda FormData (multipart) con el JWT. No fija
  // Content-Type a mano — el navegador pone el boundary del multipart.
  async function apiForm(path, formData) {
    const { data } = await sb.auth.getSession();
    const token = data.session?.access_token;
    const headers = {};
    if (token) headers['Authorization'] = 'Bearer ' + token;
    const res = await fetch((cfg.apiBase || '') + path, { method: 'POST', headers, body: formData });
    const txt = await res.text();
    let body = null;
    try { body = txt ? JSON.parse(txt) : null; } catch { body = txt; }
    if (!res.ok) {
      const msg = (body && body.error) ? (body.error + (body.detalle ? ' — ' + body.detalle : '')) : ('HTTP ' + res.status);
      const err = new Error(msg); err.status = res.status; err.body = body;
      throw err;
    }
    return body;
  }
  window.apiForm = apiForm;

  // Hook de sesión: null = cargando, false = sin sesión, objeto = logueado.
  window.useSession = () => {
    const { useState, useEffect } = React;
    const [session, setSession] = useState(null);
    useEffect(() => {
      let vivo = true;
      const resolver = () => sb.auth.getSession().then(({ data }) => { if (vivo) setSession(data.session || false); });
      const { data: sub } = sb.auth.onAuthStateChange((_e, s) => { if (vivo) setSession(s || false); });
      // Si venimos de otra app instalando la sesión (SSO), esperamos a que termine
      // antes de resolver, así no se muestra el login por una fracción de segundo.
      if (window.__ssoReady) window.__ssoReady.then(resolver); else resolver();
      return () => { vivo = false; sub.subscription.unsubscribe(); };
    }, []);
    return session;
  };
})();
