// supabase.jsx — Supabase config, auth, live data source, mock fallback.
// The anon key is public by design; access is gated by Supabase Auth + RLS
// (authenticated-only read policies). Never put the service_role key here.

const SUPABASE_URL = 'https://fxcffzcvvrieojyindpi.supabase.co';
const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ4Y2ZmemN2dnJpZW9qeWluZHBpIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzgyNTA4NTYsImV4cCI6MjA5MzgyNjg1Nn0.ZmkGaS8ESYVuJD3etSxbHM_2spZeZJv5AAc0BDWFWls';

const sb = (window.supabase && window.supabase.createClient)
  ? window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
  : null;

// ---- date ranges -----------------------------------------------------------
// Anchor "today" to the last seeded day so demo + live line up.
const ANCHOR = new Date(2026, 4, 28);
function isoOf(d) { return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; }
function addDays(d, n) { const x = new Date(d); x.setDate(x.getDate() + n); return x; }
function daysInclusive(fromISO, toISO) { return window.dayCount(fromISO, toISO); }

// Returns { from, to, pf, pt } ISO strings: current range + equally-long prior.
function rangeForPeriod(period, custom) {
  let from, to;
  if (period === 'custom' && custom) {
    from = custom.from; to = custom.to;
  } else if (period === 'weekly') {
    to = isoOf(ANCHOR); from = isoOf(addDays(ANCHOR, -6));
  } else if (period === 'annual') {
    to = isoOf(ANCHOR); from = isoOf(new Date(ANCHOR.getFullYear(), 0, 1));
  } else { // monthly (default)
    to = isoOf(ANCHOR); from = isoOf(new Date(ANCHOR.getFullYear(), ANCHOR.getMonth(), 1));
  }
  const len = daysInclusive(from, to);
  const pt = isoOf(addDays(window.parseISO(from), -1));
  const pf = isoOf(addDays(window.parseISO(from), -len));
  return { from, to, pf, pt };
}

// ---- live data source (reads real rows, aggregates by range) ---------------
const MKEYS = ['calls', 'form_fills', 'chats', 'leads_generated',
               'cases_signed', 'contracts_pending', 'contracts_lost'];

function makeLiveSource(clients, rows) {
  // metrics now link to clients by NAME (client_name) instead of a UUID.
  const byClient = {};
  clients.forEach(c => { byClient[c.name] = []; });
  rows.forEach(r => { (byClient[r.client_name] = byClient[r.client_name] || []).push(r); });

  const sumRange = (list, from, to) => {
    const acc = Object.fromEntries(MKEYS.map(k => [k, 0]));
    for (const r of list) {
      if (r.date >= from && r.date <= to) {
        for (const k of MKEYS) acc[k] += (r[k] || 0);
      }
    }
    return acc;
  };

  const clientMetrics = (id, period, custom) => {
    const { from, to, pf, pt } = rangeForPeriod(period, custom);
    const c = clients.find(x => x.id === id);
    const list = c ? (byClient[c.name] || []) : [];
    return { ...sumRange(list, from, to), prev: sumRange(list, pf, pt) };
  };

  const rollup = (period, custom) => {
    const { from, to, pf, pt } = rangeForPeriod(period, custom);
    const total = Object.fromEntries(MKEYS.map(k => [k, 0]));
    const prev = Object.fromEntries(MKEYS.map(k => [k, 0]));
    const outRows = clients.map(c => {
      const cur = sumRange(byClient[c.name] || [], from, to);
      const pv = sumRange(byClient[c.name] || [], pf, pt);
      MKEYS.forEach(k => { total[k] += cur[k]; prev[k] += pv[k]; });
      return { client: { id: c.id, name: c.name, crm_type: c.crm_type || '', region: c.region || '' }, ...cur, prev };
    });
    return { total: { ...total, prev }, rows: outRows };
  };

  return {
    kind: 'live',
    rollup, clientMetrics,
    getClient: (id) => { const c = clients.find(x => x.id === id); return c ? { ...c, region: c.region || '' } : null; },
  };
}

// ---- mock data source (fallback, same interface) ---------------------------
function makeMockSource() {
  const norm = (p) => (p === 'custom' ? 'monthly' : p);
  return {
    kind: 'mock',
    rollup: (period, custom) =>
      period === 'custom' && custom
        ? window.rollupMetricsRange(custom.from, custom.to)
        : window.rollupMetrics(norm(period)),
    clientMetrics: (id, period, custom) => {
      const c = window.getClient(id);
      return period === 'custom' && custom
        ? window.clientMetricsRange(c, custom.from, custom.to)
        : window.clientMetrics(c, norm(period));
    },
    getClient: (id) => window.getClient(id),
  };
}

// ---- fetch all metrics with pagination (Supabase caps at 1000/req) ---------
async function fetchAll(table, columns) {
  const page = 1000;
  let all = [], offset = 0;
  for (;;) {
    const { data, error } = await sb.from(table).select(columns).range(offset, offset + page - 1);
    if (error) throw error;
    all = all.concat(data);
    if (!data || data.length < page) break;
    offset += page;
  }
  return all;
}

// Loads the live source. Throws on error / empty so caller can fall back.
async function loadLiveSource() {
  if (!sb) throw new Error('supabase-js not loaded');
  // select '*' so we don't break if optional columns (crm_type, region) are absent.
  const clients = await fetchAll('clients', '*');
  if (!clients || !clients.length) throw new Error('no clients in database');
  const metrics = await fetchAll('metrics', 'client_name,date,calls,form_fills,chats,leads_generated,cases_signed,contracts_pending,contracts_lost');
  clients.sort((a, b) => a.name.localeCompare(b.name));
  return makeLiveSource(clients, metrics);
}

Object.assign(window, {
  sb, rangeForPeriod, makeLiveSource, makeMockSource, loadLiveSource,
  SUPABASE_CONFIGURED: !!sb,
});
