// Live data wiring for Supermetrics.
//
// Pattern: each KPI/chart calls useSupermetrics(query) with a query object.
// If the client has a corresponding `supermetrics` mapping (Google Ads
// customer id, Meta account id, etc.), the hook hits /api/supermetrics and
// returns the live value. If the mapping isn't there, it returns
// { ready: false } so the caller can fall back to its mock value.
//
// To wire another KPI: pass the right `query` here and read `data` /
// `loading` / `error` / `ready` from the hook. No more, no less.

const { useState: smState, useEffect: smEffect, useMemo: smMemo } = React;

function useSupermetrics(query, deps = []) {
  const [state, setState] = smState({ loading: true, data: null, error: null, ready: !!query });

  smEffect(() => {
    if (!query) {
      setState({ loading: false, data: null, error: null, ready: false });
      return;
    }
    let cancelled = false;
    setState((s) => ({ ...s, loading: true, error: null }));
    fetch('/api/supermetrics', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(query),
    })
      .then(async (res) => {
        const body = await res.json().catch(() => ({}));
        if (!res.ok) throw new Error(body.error || `HTTP ${res.status}`);
        return body;
      })
      .then((data) => {
        if (cancelled) return;
        setState({ loading: false, data, error: null, ready: true });
      })
      .catch((e) => {
        if (cancelled) return;
        setState({ loading: false, data: null, error: e.message || String(e), ready: true });
      });
    return () => { cancelled = true; };
  // eslint-disable-next-line
  }, deps);

  return state;
}
window.useSupermetrics = useSupermetrics;

// Helper: sum a numeric column from a Supermetrics JSON response.
// Supermetrics enterprise JSON returns rows under data.data[]. The first row
// is typically the header; we skip it when the first cell isn't a number.
function sumColumn(payload, columnIndex) {
  if (!payload) return null;
  const rows = payload?.data?.data || payload?.data || [];
  if (!Array.isArray(rows) || rows.length === 0) return null;
  let total = 0;
  let counted = 0;
  for (const row of rows) {
    const cell = Array.isArray(row) ? row[columnIndex] : row?.[columnIndex];
    const n = typeof cell === 'number' ? cell : parseFloat(cell);
    if (!Number.isFinite(n)) continue;
    total += n;
    counted += 1;
  }
  return counted > 0 ? total : null;
}
window.sumSupermetricsColumn = sumColumn;

// Small visual pill that shows whether a KPI is currently live or mock.
function LivePill({ live, loading, error }) {
  let label = 'Mock';
  let bg = 'rgba(26,25,25,0.06)';
  let fg = 'var(--ink-stone)';
  if (loading) { label = 'Loading'; }
  else if (error) { label = 'Live (error)'; bg = 'rgba(220, 38, 38, 0.10)'; fg = '#b91c1c'; }
  else if (live) { label = 'Live'; bg = 'rgba(16, 185, 129, 0.14)'; fg = '#047857'; }
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      fontSize: 9.5, letterSpacing: '0.08em', textTransform: 'uppercase',
      padding: '2px 6px', borderRadius: 999, background: bg, color: fg,
      fontWeight: 600, marginLeft: 6,
    }}>
      {label}
    </span>
  );
}
window.LivePill = LivePill;

// ── Per-source hooks for RCG live data ───────────────────
//
// These hooks read the entity's `supermetrics` config (only RCG has one
// currently) and only fire a query when all the required IDs are present.
// When the config is missing, they return { ready: false } so the calling
// component can fall back to its mock value cleanly.
//
// ds_id values are Supermetrics' canonical codes (visible in the Query
// Manager's generated query JSON). If a connector ever rejects a query for
// "unknown ds_id", override the constant here.

const DS_GA4 = 'GA4';
const DS_LINKEDIN_ADS = 'LNA';
const DS_LINKEDIN_PAGE = 'LIP';
const DS_ACTIVE_CAMPAIGN = 'AC';

function buildSmQuery({ ds_id, ds_user_id, ds_accounts, fields, dateRange = 'last_30_days' }) {
  if (!ds_user_id || !ds_accounts) return null;
  return {
    ds_id,
    ds_user_id,
    ds_accounts,
    date_range_type: dateRange,
    fields,
    max_rows: 5000,
  };
}

// GA4 — single-field aggregate (Sessions, Conversions, Users, etc.).
function useGa4Total(client, field) {
  const cfg = client?.supermetrics;
  const query = client?.isSelf ? buildSmQuery({
    ds_id: DS_GA4,
    ds_user_id: cfg?.dsUserId,
    ds_accounts: cfg?.ga4?.propertyId,
    fields: field,
  }) : null;
  const state = useSupermetrics(query, [client?.id, field, cfg?.ga4?.propertyId]);
  return { ...state, value: sumColumn(state.data, 0) };
}
window.useGa4Total = useGa4Total;

// LinkedIn Ads — single-field aggregate (Cost, Impressions, Clicks, Conversions).
function useLinkedinAdsTotal(client, field) {
  const cfg = client?.supermetrics;
  const query = client?.isSelf ? buildSmQuery({
    ds_id: DS_LINKEDIN_ADS,
    ds_user_id: cfg?.dsUserId,
    ds_accounts: cfg?.linkedinAds?.accountId,
    fields: field,
  }) : null;
  const state = useSupermetrics(query, [client?.id, field, cfg?.linkedinAds?.accountId]);
  return { ...state, value: sumColumn(state.data, 0) };
}
window.useLinkedinAdsTotal = useLinkedinAdsTotal;

// ActiveCampaign — single-field aggregate (Emailssent, Opens, Clicks, etc.).
function useActiveCampaignTotal(client, field) {
  const cfg = client?.supermetrics;
  const query = client?.isSelf ? buildSmQuery({
    ds_id: DS_ACTIVE_CAMPAIGN,
    ds_user_id: cfg?.dsUserId,
    ds_accounts: cfg?.activeCampaign?.accountId,
    fields: field,
  }) : null;
  const state = useSupermetrics(query, [client?.id, field, cfg?.activeCampaign?.accountId]);
  return { ...state, value: sumColumn(state.data, 0) };
}
window.useActiveCampaignTotal = useActiveCampaignTotal;
