// ============================================================================
// Supabase client + data service
// ============================================================================
// Loaded AFTER lib/config.jsx (which sets window.EMPHASIS_ENV).
// Exposes:
//   - window.supabase     — the Supabase client instance
//   - window.db           — high-level data service (db.appointments.list(), etc.)
//   - window.SB_READY     — true when client is initialized and reachable
//
// If credentials aren't set yet (you haven't replaced YOUR_DEV_PROJECT in
// config.jsx), the client still loads but every query is a no-op that falls
// back to the in-memory mocks from data.jsx. This lets prototype + production
// run from the same code path.
// ============================================================================

(() => {
  const env = window.EMPHASIS_ENV;
  const credsConfigured = !env.supabaseUrl.includes('YOUR_') && !env.supabaseAnonKey.includes('YOUR_');

  if (!credsConfigured) {
    console.warn('[Supabase] Credentials not set in lib/config.jsx — running in MOCK mode.');
    window.SB_READY = false;
    window.supabase = null;
    window.db = makeMockDb();
    return;
  }

  // The Supabase JS SDK is loaded via CDN in index.html and exposes a global
  // `supabase` object with a `createClient` factory.
  const { createClient } = window.supabase || {};
  if (!createClient) {
    console.error('[Supabase] SDK not loaded. Check the CDN <script> in index.html.');
    window.SB_READY = false;
    window.db = makeMockDb();
    return;
  }

  const client = createClient(env.supabaseUrl, env.supabaseAnonKey, {
    auth: { persistSession: true, autoRefreshToken: true, storageKey: `emphasis-auth-${env.name}` },
  });

  window.supabase = client;
  window.SB_READY = true;
  window.db = makeRealDb(client);
  console.log(`[Supabase] Connected to ${env.name} → ${env.supabaseUrl}`);
})();

// ============================================================================
// Real DB service (queries against Supabase)
// ============================================================================
function makeRealDb(sb) {
  return {
    // ---------- AUTH ----------
    auth: {
      async signInWithLineToken(idToken) {
        // In production, exchange LINE ID token for a Supabase session.
        // Two options: (1) Supabase Auth + custom JWT, (2) edge function that
        // verifies LINE token and signs a Supabase JWT. For the prototype we
        // upsert into users and return the row.
        const { data, error } = await sb.from('users').select('*').eq('line_user_id', idToken).maybeSingle();
        return { user: data, error };
      },
      async signOut() { return sb.auth.signOut(); },
      session() { return sb.auth.getSession(); },
    },

    // ---------- LOOKUP TABLES ----------
    apptTypes: {
      list: () => sb.from('appt_type').select('*').eq('is_active', true).order('sort_order'),
      upsert: (rows) => sb.from('appt_type').upsert(rows),
    },
    leadSources: {
      list: () => sb.from('lead_source').select('*').eq('is_active', true).order('sort_order'),
      upsert: (rows) => sb.from('lead_source').upsert(rows),
    },

    // ---------- USERS ----------
    users: {
      me: () => sb.from('users').select('*').eq('id', currentUid()).single(),
      list: () => sb.from('users').select('*').order('name'),
      downlines: (uplineId) => sb.from('users').select('*').eq('upline_id', uplineId),
      update: (id, patch) => sb.from('users').update(patch).eq('id', id),
    },

    // ---------- APPOINTMENTS ----------
    appointments: {
      list: (filters = {}) => {
        let q = sb.from('appointments').select(`
          *,
          prospect:prospects(id, name, ig_handle, ig_avatar, country, source_id),
          type:appt_type(*),
          owner:owner_id(id, name, color, avatar),
          dl:dl_id(id, name, color, avatar)
        `).order('scheduled_at');
        if (filters.from) q = q.gte('scheduled_at', filters.from);
        if (filters.to)   q = q.lte('scheduled_at', filters.to);
        if (filters.status) q = q.eq('status', filters.status);
        return q;
      },
      create: (row) => sb.from('appointments').insert(row).select().single(),
      update: (id, patch) => sb.from('appointments').update(patch).eq('id', id).select().single(),
      delete: (id) => sb.from('appointments').delete().eq('id', id),
    },

    // ---------- PROSPECTS ----------
    prospects: {
      list: () => sb.from('prospects').select('*').order('created_at', { ascending: false }),
      create: (row) => sb.from('prospects').insert(row).select().single(),
      update: (id, patch) => sb.from('prospects').update(patch).eq('id', id),
    },

    // ---------- CUSTOMERS (6W) ----------
    customers: {
      list: () => sb.from('customers').select('*, weight_log(*), bodykey_usage(*)'),
      create: (row) => sb.from('customers').insert(row).select().single(),
      logWeight: (customerId, week, weight, note) =>
        sb.from('weight_log').insert({ customer_id: customerId, week, weight, note }),
    },

    // ---------- ADMIN ----------
    meetings: {
      list: () => sb.from('admin_meetings').select('*').order('day_of_week'),
      create: (row) => sb.from('admin_meetings').insert(row).select().single(),
      delete: (id) => sb.from('admin_meetings').delete().eq('id', id),
    },
    broadcasts: {
      list: () => sb.from('admin_broadcasts').select('*').order('sent_at', { ascending: false }),
      send:  (row) => sb.from('admin_broadcasts').insert(row).select().single(),
    },

    // ---------- USER SETTINGS ----------
    settings: {
      get: () => sb.from('app_settings').select('config').eq('user_id', currentUid()).maybeSingle(),
      save: (cfg) => sb.from('app_settings').upsert({ user_id: currentUid(), config: cfg, updated_at: new Date().toISOString() }),
    },

    // ---------- STORAGE: appointment photos ----------
    photos: {
      async upload(appointmentId, file) {
        const path = `${appointmentId}/${Date.now()}-${file.name}`;
        const { data, error } = await sb.storage.from('appt-photos').upload(path, file);
        if (error) return { error };
        await sb.from('appointment_photos').insert({ appointment_id: appointmentId, storage_path: data.path });
        return { path: data.path };
      },
      async listForAppt(appointmentId) {
        const { data } = await sb.from('appointment_photos').select('*').eq('appointment_id', appointmentId);
        return data || [];
      },
      url(path) { return sb.storage.from('appt-photos').getPublicUrl(path).data.publicUrl; },
    },
  };

  function currentUid() {
    const u = window.__currentUser;
    return u?.id || null;
  }
}

// ============================================================================
// Mock DB (used when Supabase isn't configured) — reads from window.* mocks
// ============================================================================
function makeMockDb() {
  const ok = (data) => Promise.resolve({ data, error: null });
  return {
    auth: {
      signInWithLineToken: () => ok(window.TEAM?.[0] || null),
      signOut: () => ok(null),
      session: () => ok(null),
    },
    apptTypes:   { list: () => ok(window.APPT_TYPES || []),   upsert: () => ok(null) },
    leadSources: { list: () => ok(window.LEAD_SOURCES || []), upsert: () => ok(null) },
    users: {
      me:       () => ok(window.TEAM?.[0] || null),
      list:     () => ok(window.TEAM || []),
      downlines:() => ok((window.TEAM || []).slice(1)),
      update:   () => ok(null),
    },
    appointments: {
      list:   () => ok(window.APPOINTMENTS || []),
      create: (row) => ok({ id: 'mock-' + Date.now(), ...row }),
      update: (id, patch) => ok({ id, ...patch }),
      delete: () => ok(null),
    },
    prospects:  { list: () => ok([]),                                 create: (r) => ok({ id: 'mp-' + Date.now(), ...r }), update: () => ok(null) },
    customers:  { list: () => ok(window.CUSTOMERS_6W || []),          create: (r) => ok({ id: 'mc-' + Date.now(), ...r }), logWeight: () => ok(null) },
    meetings:   { list: () => ok(window.ADMIN_MEETINGS || []),        create: (r) => ok({ id: 'mm-' + Date.now(), ...r }), delete: () => ok(null) },
    broadcasts: { list: () => ok(window.ADMIN_BROADCASTS || []),      send:   (r) => ok({ id: 'mb-' + Date.now(), ...r }) },
    settings:   { get: () => ok(null), save: () => ok(null) },
    photos:     { upload: () => ok({ path: '' }), listForAppt: () => Promise.resolve([]), url: () => '' },
  };
}
