#!/usr/bin/env bash
# ops-marketing-dash — pre-gathers data from all configured marketing channels
# Output: JSON object with data from each channel (null for unconfigured)
# v1.6: project-aware — reads preferences.json marketing.{default_project,projects.<name>.<channel>}
#       and resolves cred refs (env:VAR | doppler:project/config/SECRET | inline)

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OPS_PLUGIN_ROOT_FALLBACK="${SCRIPT_DIR}/.." . "${SCRIPT_DIR}/../lib/registry-path.sh"
# resolve_cred, ga4_resolve, gsc_resolve, marketing_channels_status
# shellcheck disable=SC1091
. "${SCRIPT_DIR}/../scripts/lib/ga4-resolve.sh"
# ga4_auth_token + ga4_run_report (shared with ops-marketing-autopilot)
# shellcheck disable=SC1091
. "${SCRIPT_DIR}/../scripts/lib/ga4-data-api.sh"
PREFS="${OPS_DATA_DIR}/preferences.json"

# Pull a value from preferences.json marketing.projects.<project>.<channel>.<field>.
# $1 project, $2 channel, $3 field. Echoes nothing if missing or prefs absent.
prefs_get() {
  [ -f "$PREFS" ] || return 0
  jq -r --arg p "$1" --arg c "$2" --arg f "$3" \
    '.marketing.projects[$p][$c][$f] // empty' "$PREFS" 2>/dev/null
}

# Project selection: --project <name> arg, OPS_MARKETING_PROJECT env, or
# marketing.default_project from prefs. Empty if no project context.
PROJECT=""
for ((i=1; i<=$#; i++)); do
  if [ "${!i}" = "--project" ]; then
    j=$((i+1))
    PROJECT="${!j:-}"
    break
  fi
done
PROJECT="${PROJECT:-${OPS_MARKETING_PROJECT:-}}"
if [ -z "$PROJECT" ] && [ -f "$PREFS" ]; then
  PROJECT="$(jq -r '.marketing.default_project // empty' "$PREFS" 2>/dev/null || true)"
fi

# Credential resolution — three-tier:
#   1. Project config in preferences.json (NEW, primary)
#   2. Flat env / `claude plugin config get` (legacy)
#   3. Doppler with bare key name (legacy)
get_cred() {
  local proj_channel="$1"  # e.g. "klaviyo.private_key"
  local env_var="$2"
  local plugin_key="$3"
  local doppler_key="${4:-}"

  local val=""
  if [ -n "$PROJECT" ]; then
    local channel="${proj_channel%%.*}"
    local field="${proj_channel#*.}"
    val="$(resolve_cred "$(prefs_get "$PROJECT" "$channel" "$field")")"
  fi
  if [ -z "$val" ]; then val="${!env_var:-}"; fi
  if [ -z "$val" ]; then val="$(claude plugin config get "$plugin_key" 2>/dev/null || echo "")"; fi
  if [ -z "$val" ] && [ -n "$doppler_key" ]; then
    val="$(doppler secrets get "$doppler_key" --plain 2>/dev/null || echo "")"
  fi
  printf '%s' "$val"
}

KLAVIYO_KEY="$(get_cred 'klaviyo.private_key' KLAVIYO_PRIVATE_KEY klaviyo_private_key KLAVIYO_PRIVATE_KEY)"
META_TOKEN="$(get_cred 'meta.access_token' META_ADS_TOKEN meta_ads_token META_ADS_TOKEN)"
META_ACCOUNT="$(get_cred 'meta.ad_account_id' META_AD_ACCOUNT_ID meta_ad_account_id META_AD_ACCOUNT_ID)"
GA4_PROPERTY="$(get_cred 'ga4.property_id' GA4_PROPERTY_ID ga4_property_id)"
GSC_SITE="$(get_cred 'gsc.site_url' GOOGLE_SEARCH_CONSOLE_SITE google_search_console_site)"
GADS_DEV_TOKEN="$(get_cred 'google_ads.developer_token' GOOGLE_ADS_DEVELOPER_TOKEN google_ads_developer_token)"
GADS_CLIENT_ID="${GOOGLE_ADS_CLIENT_ID:-$(claude plugin config get google_ads_client_id 2>/dev/null || echo "")}"
GADS_CLIENT_SECRET="${GOOGLE_ADS_CLIENT_SECRET:-$(claude plugin config get google_ads_client_secret 2>/dev/null || echo "")}"
GADS_REFRESH_TOKEN="$(get_cred 'google_ads.refresh_token' GOOGLE_ADS_REFRESH_TOKEN google_ads_refresh_token GOOGLE_ADS_REFRESH_TOKEN)"
GADS_CUSTOMER_ID="$(get_cred 'google_ads.customer_id' GOOGLE_ADS_CUSTOMER_ID google_ads_customer_id)"
GADS_LOGIN_CUSTOMER_ID="${GOOGLE_ADS_LOGIN_CUSTOMER_ID:-$(claude plugin config get google_ads_login_customer_id 2>/dev/null || echo "")}"
INSTAGRAM_ACCOUNT_ID="$(get_cred 'instagram.account_id' INSTAGRAM_ACCOUNT_ID instagram_account_id)"
META_APP_SECRET="$(get_cred 'meta.app_secret' META_APP_SECRET meta_app_secret META_APP_SECRET)"

# Compute appsecret_proof for projects that require it (Meta system-user tokens
# and any project with app_secret configured). Empty string when no secret.
META_PROOF=""
if [ -n "$META_TOKEN" ] && [ -n "$META_APP_SECRET" ]; then
  META_PROOF=$(printf '%s' "$META_TOKEN" | openssl dgst -sha256 -hmac "$META_APP_SECRET" -hex 2>/dev/null | awk '{print $NF}')
fi

# Build query-string fragment to append. Empty when no proof.
META_PROOF_QS=""
[ -n "$META_PROOF" ] && META_PROOF_QS="&appsecret_proof=${META_PROOF}"

# Strip dashes from customer ID (API requires no dashes)
GADS_CUSTOMER_ID="${GADS_CUSTOMER_ID//-/}"

TODAY=$(date +%Y-%m-%d)

# --- Klaviyo ---
gather_klaviyo() {
  if [ -z "$KLAVIYO_KEY" ]; then
    echo "null"
    return
  fi

  # Get total subscriber count across all lists
  LISTS=$(curl -gsS --max-time 5 "https://a.klaviyo.com/api/lists/?fields[list]=name,id,profile_count" \
    -H "Authorization: Klaviyo-API-Key ${KLAVIYO_KEY}" \
    -H "revision: 2024-10-15" 2>/dev/null)

  TOTAL_SUBS=$(echo "$LISTS" | jq '[.data[].attributes.profile_count // 0] | add // 0' 2>/dev/null || echo "0")

  # Get last campaign stats
  CAMPAIGNS=$(curl -gsS --max-time 5 "https://a.klaviyo.com/api/campaigns/?filter=equals(messages.channel,'email')&sort=-created_at&page[size]=1&fields[campaign]=name,status,send_time" \
    -H "Authorization: Klaviyo-API-Key ${KLAVIYO_KEY}" \
    -H "revision: 2024-10-15" 2>/dev/null)

  LAST_CAMPAIGN_NAME=$(echo "$CAMPAIGNS" | jq -r '.data[0].attributes.name // "none"' 2>/dev/null || echo "none")
  LAST_CAMPAIGN_STATUS=$(echo "$CAMPAIGNS" | jq -r '.data[0].attributes.status // "none"' 2>/dev/null || echo "none")
  LAST_CAMPAIGN_ID=$(echo "$CAMPAIGNS" | jq -r '.data[0].id // empty' 2>/dev/null || echo "")

  # Open rate (0.0-1.0) for last campaign — feeds marketing health score email component.
  OPEN_RATE="0"
  if [ -n "$LAST_CAMPAIGN_ID" ]; then
    VALUES=$(curl -gsS --max-time 5 -X POST "https://a.klaviyo.com/api/campaign-values-reports/" \
      -H "Authorization: Klaviyo-API-Key ${KLAVIYO_KEY}" \
      -H "revision: 2024-10-15" \
      -H "Content-Type: application/json" \
      -d "{\"data\":{\"type\":\"campaign-values-report\",\"attributes\":{\"statistics\":[\"open_rate\"],\"timeframe\":{\"key\":\"last_30_days\"},\"filter\":\"equals(campaign_id,\\\"${LAST_CAMPAIGN_ID}\\\")\"}}}" 2>/dev/null)
    OPEN_RATE=$(echo "$VALUES" | jq -r '.data.attributes.results[0].statistics.open_rate // 0' 2>/dev/null || echo "0")
  fi

  jq -n \
    --argjson subs "$TOTAL_SUBS" \
    --arg last_campaign "$LAST_CAMPAIGN_NAME" \
    --arg last_status "$LAST_CAMPAIGN_STATUS" \
    --argjson open_rate "${OPEN_RATE:-0}" \
    '{subscribers: $subs, last_campaign: $last_campaign, last_campaign_status: $last_status, open_rate: $open_rate}'
}

# --- Meta Ads ---
gather_meta() {
  if [ -z "$META_TOKEN" ] || [ -z "$META_ACCOUNT" ]; then
    echo "null"
    return
  fi

  INSIGHTS=$(curl -gsS --max-time 5 "https://graph.facebook.com/v18.0/${META_ACCOUNT}/insights?fields=spend,impressions,clicks,ctr,cpc,actions,action_values&date_preset=last_7d&level=account${META_PROOF_QS}" \
    -H "Authorization: Bearer ${META_TOKEN}" 2>/dev/null)

  SPEND=$(echo "$INSIGHTS" | jq -r '.data[0].spend // "0"' 2>/dev/null || echo "0")
  IMPRESSIONS=$(echo "$INSIGHTS" | jq -r '.data[0].impressions // "0"' 2>/dev/null || echo "0")
  CLICKS=$(echo "$INSIGHTS" | jq -r '.data[0].clicks // "0"' 2>/dev/null || echo "0")
  CTR=$(echo "$INSIGHTS" | jq -r '.data[0].ctr // "0"' 2>/dev/null || echo "0")

  # Extract purchase count and revenue from actions/action_values
  PURCHASES=$(echo "$INSIGHTS" | jq -r '[.data[0].actions[]? | select(.action_type == "purchase") | .value] | first // "0"' 2>/dev/null || echo "0")
  PURCHASE_VALUE=$(echo "$INSIGHTS" | jq -r '[.data[0].action_values[]? | select(.action_type == "purchase") | .value] | first // "0"' 2>/dev/null || echo "0")

  # ROAS = purchase_value / spend
  ROAS=$(awk "BEGIN {s=$SPEND+0; v=$PURCHASE_VALUE+0; if (s>0) printf \"%.2f\", v/s; else print \"0\"}")

  jq -n \
    --arg spend "$SPEND" \
    --arg impressions "$IMPRESSIONS" \
    --arg clicks "$CLICKS" \
    --arg ctr "$CTR" \
    --arg purchases "$PURCHASES" \
    --arg purchase_value "$PURCHASE_VALUE" \
    --arg roas "$ROAS" \
    '{spend: $spend, impressions: $impressions, clicks: $clicks, ctr: $ctr, purchases: $purchases, purchase_value: $purchase_value, roas: $roas}'
}

# --- GA4 ---
# Auth + transport now live in scripts/lib/ga4-data-api.sh (shared with autopilot).
# Local wrapper kept as a thin shim for backward compatibility with prior callers.
_ga4_auth_token() { ga4_auth_token; }

gather_ga4() {
  if [ -z "$GA4_PROPERTY" ] || [ "$GA4_PROPERTY" = "0" ]; then
    echo "null"
    return
  fi

  local REPORT
  REPORT=$(ga4_run_report "$GA4_PROPERTY" '{
      "dateRanges": [{"startDate": "7daysAgo", "endDate": "today"}],
      "metrics": [
        {"name": "sessions"},
        {"name": "totalUsers"},
        {"name": "conversions"},
        {"name": "screenPageViews"},
        {"name": "totalRevenue"}
      ]
    }')
  if [ -z "$REPORT" ] || [ "$REPORT" = "{}" ]; then
    echo "null"
    return
  fi

  local SESSIONS USERS CONVERSIONS PAGEVIEWS REVENUE CVR
  SESSIONS=$(printf '%s' "$REPORT" | jq -r '.rows[0].metricValues[0].value // "0"' 2>/dev/null || echo "0")
  USERS=$(printf '%s' "$REPORT" | jq -r '.rows[0].metricValues[1].value // "0"' 2>/dev/null || echo "0")
  CONVERSIONS=$(printf '%s' "$REPORT" | jq -r '.rows[0].metricValues[2].value // "0"' 2>/dev/null || echo "0")
  PAGEVIEWS=$(printf '%s' "$REPORT" | jq -r '.rows[0].metricValues[3].value // "0"' 2>/dev/null || echo "0")
  REVENUE=$(printf '%s' "$REPORT" | jq -r '.rows[0].metricValues[4].value // "0"' 2>/dev/null || echo "0")

  CVR=$(awk "BEGIN {s=$SESSIONS+0; c=$CONVERSIONS+0; if (s>0) printf \"%.2f\", (c/s)*100; else print \"0\"}")

  jq -n \
    --arg sessions "$SESSIONS" \
    --arg users "$USERS" \
    --arg conversions "$CONVERSIONS" \
    --arg pageviews "$PAGEVIEWS" \
    --arg revenue "$REVENUE" \
    --arg cvr "$CVR" \
    '{sessions: $sessions, users: $users, conversions: $conversions, pageviews: $pageviews, revenue: $revenue, cvr: $cvr}'
}

# --- Google Search Console ---
gather_gsc() {
  if [ -z "$GSC_SITE" ]; then
    echo "null"
    return
  fi

  GSC_TOKEN=$(gcloud auth application-default print-access-token 2>/dev/null || echo "")
  if [ -z "$GSC_TOKEN" ]; then
    echo "null"
    return
  fi

  GSC_SITE_ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${GSC_SITE}', safe=''))" 2>/dev/null \
    || echo "${GSC_SITE}" | sed 's|:|%3A|g; s|/|%2F|g')

  START_DATE=$(date -v-28d +%Y-%m-%d 2>/dev/null || date -d '28 days ago' +%Y-%m-%d 2>/dev/null || echo "")
  if [ -z "$START_DATE" ]; then
    echo "null"
    return
  fi

  REPORT=$(curl -gsS --max-time 5 -X POST "https://searchconsole.googleapis.com/webmasters/v3/sites/${GSC_SITE_ENCODED}/searchAnalytics/query" \
    -H "Authorization: Bearer ${GSC_TOKEN}" \
    -H "Content-Type: application/json" \
    -d "{\"startDate\": \"${START_DATE}\", \"endDate\": \"${TODAY}\", \"dimensions\": [], \"rowLimit\": 1}" 2>/dev/null)

  CLICKS=$(echo "$REPORT" | jq -r '.rows[0].clicks // 0' 2>/dev/null || echo "0")
  IMPRESSIONS=$(echo "$REPORT" | jq -r '.rows[0].impressions // 0' 2>/dev/null || echo "0")
  CTR=$(echo "$REPORT" | jq -r '.rows[0].ctr // 0' 2>/dev/null || echo "0")
  POSITION=$(echo "$REPORT" | jq -r '.rows[0].position // 0' 2>/dev/null || echo "0")

  jq -n \
    --argjson clicks "$CLICKS" \
    --argjson impressions "$IMPRESSIONS" \
    --argjson ctr "$CTR" \
    --argjson position "$POSITION" \
    '{clicks: $clicks, impressions: $impressions, ctr: $ctr, avg_position: $position}'
}

# --- Instagram ---
gather_instagram() {
  if [ -z "$META_TOKEN" ]; then
    echo "null"
    return
  fi

  # Resolve IG account ID if not cached
  IG_ID="$INSTAGRAM_ACCOUNT_ID"
  if [ -z "$IG_ID" ]; then
    IG_ID=$(curl -gsS --max-time 5 "https://graph.facebook.com/v21.0/me/accounts?fields=instagram_business_account${META_PROOF_QS}" \
      -H "Authorization: Bearer ${META_TOKEN}" 2>/dev/null | jq -r '.data[0].instagram_business_account.id // empty')
    [ -n "$IG_ID" ] && claude plugin config set instagram_account_id "$IG_ID" 2>/dev/null
  fi

  if [ -z "$IG_ID" ]; then
    echo "null"
    return
  fi

  # Account stats
  ACCOUNT=$(curl -gsS --max-time 5 "https://graph.facebook.com/v21.0/${IG_ID}?fields=followers_count,media_count${META_PROOF_QS}" \
    -H "Authorization: Bearer ${META_TOKEN}" 2>/dev/null)
  FOLLOWERS=$(echo "$ACCOUNT" | jq -r '.followers_count // 0')
  MEDIA_COUNT=$(echo "$ACCOUNT" | jq -r '.media_count // 0')

  # Reach last 7d
  END_DATE=$(date +%Y-%m-%d)
  START_DATE=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d '7 days ago' +%Y-%m-%d 2>/dev/null || echo "")
  REACH=0
  if [ -n "$START_DATE" ]; then
    INSIGHTS=$(curl -gsS --max-time 5 "https://graph.facebook.com/v21.0/${IG_ID}/insights?metric=reach&period=day&since=${START_DATE}&until=${END_DATE}${META_PROOF_QS}" \
      -H "Authorization: Bearer ${META_TOKEN}" 2>/dev/null)
    REACH=$(echo "$INSIGHTS" | jq '[.data[]?.values[]?.value | tonumber] | add // 0' 2>/dev/null || echo "0")
  fi

  jq -n \
    --argjson followers "$FOLLOWERS" \
    --argjson media_count "$MEDIA_COUNT" \
    --argjson reach_7d "$REACH" \
    '{followers: $followers, media_count: $media_count, reach_7d: $reach_7d}'
}

# --- Google Ads ---
gather_google_ads() {
  if [ -z "$GADS_REFRESH_TOKEN" ] || [ -z "$GADS_DEV_TOKEN" ]; then
    echo "null"
    return
  fi

  # Refresh access token
  GADS_ACCESS_TOKEN=$(curl -gsS --max-time 5 -X POST https://oauth2.googleapis.com/token \
    --data "client_id=${GADS_CLIENT_ID}&client_secret=${GADS_CLIENT_SECRET}&refresh_token=${GADS_REFRESH_TOKEN}&grant_type=refresh_token" \
    | jq -r '.access_token // empty')
  if [ -z "$GADS_ACCESS_TOKEN" ]; then
    echo "null"
    return
  fi

  # Campaign summary (last 7 days)
  curl -gsS --max-time 5 -X POST \
    "https://googleads.googleapis.com/v23/customers/${GADS_CUSTOMER_ID}/googleAds:searchStream" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${GADS_ACCESS_TOKEN}" \
    -H "developer-token: ${GADS_DEV_TOKEN}" \
    ${GADS_LOGIN_CUSTOMER_ID:+-H "login-customer-id: ${GADS_LOGIN_CUSTOMER_ID}"} \
    --data-binary '{"query": "SELECT campaign.id, campaign.name, campaign.status, metrics.cost_micros, metrics.impressions, metrics.clicks, metrics.conversions, metrics.conversions_value FROM campaign WHERE segments.date DURING LAST_7_DAYS AND campaign.status != REMOVED ORDER BY metrics.cost_micros DESC LIMIT 20"}' \
    2>/dev/null || echo "null"
}

# Run all in parallel. VAR=$(fn) & does NOT propagate assignments to the parent
# shell after `wait` (the assignment happens in the backgrounded subshell only),
# so write each gatherer's stdout to a tempfile and read them back post-wait.
# This mirrors the pattern already used in bin/ops-external and bin/ops-discover-external.
TMPDIR_MD=$(mktemp -d)
trap 'rm -rf "$TMPDIR_MD"' EXIT

( gather_klaviyo     > "$TMPDIR_MD/klaviyo.json"   ) &
( gather_meta        > "$TMPDIR_MD/meta.json"      ) &
( gather_ga4         > "$TMPDIR_MD/ga4.json"       ) &
( gather_gsc         > "$TMPDIR_MD/gsc.json"       ) &
( gather_google_ads  > "$TMPDIR_MD/google_ads.json") &
( gather_instagram   > "$TMPDIR_MD/instagram.json" ) &
wait

KLAVIYO_DATA=$(cat "$TMPDIR_MD/klaviyo.json"    2>/dev/null); KLAVIYO_DATA=${KLAVIYO_DATA:-null}
META_DATA=$(cat "$TMPDIR_MD/meta.json"          2>/dev/null); META_DATA=${META_DATA:-null}
GA4_DATA=$(cat "$TMPDIR_MD/ga4.json"            2>/dev/null); GA4_DATA=${GA4_DATA:-null}
GSC_DATA=$(cat "$TMPDIR_MD/gsc.json"            2>/dev/null); GSC_DATA=${GSC_DATA:-null}
GADS_DATA=$(cat "$TMPDIR_MD/google_ads.json"    2>/dev/null); GADS_DATA=${GADS_DATA:-null}
INSTAGRAM_DATA=$(cat "$TMPDIR_MD/instagram.json" 2>/dev/null); INSTAGRAM_DATA=${INSTAGRAM_DATA:-null}

# Compute blended ROAS across Meta + Google Ads
META_SPEND=$(echo "$META_DATA" | jq -r '.spend // "0"' 2>/dev/null || echo "0")
META_REV=$(echo "$META_DATA" | jq -r '.purchase_value // "0"' 2>/dev/null || echo "0")
GADS_SPEND_RAW=$(echo "$GADS_DATA" | jq '[.[].results[]?.metrics.costMicros // "0" | tonumber] | add / 1000000 // 0' 2>/dev/null || echo "0")
GADS_REV_RAW=$(echo "$GADS_DATA" | jq '[.[].results[]?.metrics.conversionsValue // "0" | tonumber] | add // 0' 2>/dev/null || echo "0")
TOTAL_SPEND=$(awk "BEGIN { printf \"%.2f\", ${META_SPEND:-0} + ${GADS_SPEND_RAW:-0} }")
TOTAL_REV=$(awk "BEGIN { printf \"%.2f\", ${META_REV:-0} + ${GADS_REV_RAW:-0} }")
BLENDED_ROAS=$(awk "BEGIN { if (${TOTAL_SPEND:-0} > 0) printf \"%.2f\", ${TOTAL_REV:-0} / ${TOTAL_SPEND:-1}; else print \"0\" }")

# Compute marketing health score (0-100)
# ROAS score (0-30)
ROAS_SCORE=$(awk "BEGIN { r = ${BLENDED_ROAS:-0}; if (r >= 3) print 30; else if (r >= 1) print 15; else print 0 }")
# Email open rate score (0-20) — derived from Klaviyo last-campaign open rate
# when available; falls back to 0 when we have no campaign data. Thresholds
# come from SKILL.md §Marketing Health Score: >=20% → 20pt, 10-20% → 10pt.
KLAVIYO_OPEN_RATE=$(echo "$KLAVIYO_DATA" | jq -r '.open_rate // "0"' 2>/dev/null || echo "0")
EMAIL_SCORE=$(awk "BEGIN { r = ${KLAVIYO_OPEN_RATE:-0}; if (r >= 0.20) print 20; else if (r >= 0.10) print 10; else print 0 }")
# Channel diversification (0-20): count active platforms.
# Compare numerically — after the tempfile fix these fields can be JSON null or
# numeric strings like "0.00", neither of which a literal != "0" string test
# handles correctly.
ACTIVE_CHANNELS=0
is_positive() { awk -v v="${1:-0}" 'BEGIN { v = v + 0; exit !(v > 0) }'; }
META_SPEND_CHECK=$(echo "$META_DATA" | jq -r '.spend // 0' 2>/dev/null || echo 0)
KLAVIYO_SUBS_CHECK=$(echo "$KLAVIYO_DATA" | jq -r '.subscribers // 0' 2>/dev/null || echo 0)
INSTAGRAM_FOLLOWERS_CHECK=$(echo "$INSTAGRAM_DATA" | jq -r '.followers // 0' 2>/dev/null || echo 0)
is_positive "$META_SPEND_CHECK"          && ACTIVE_CHANNELS=$((ACTIVE_CHANNELS + 1))
is_positive "$GADS_SPEND_RAW"            && ACTIVE_CHANNELS=$((ACTIVE_CHANNELS + 1))
is_positive "$KLAVIYO_SUBS_CHECK"        && ACTIVE_CHANNELS=$((ACTIVE_CHANNELS + 1))
is_positive "$INSTAGRAM_FOLLOWERS_CHECK" && ACTIVE_CHANNELS=$((ACTIVE_CHANNELS + 1))
DIV_SCORE=$([ $ACTIVE_CHANNELS -ge 3 ] && echo 20 || ([ $ACTIVE_CHANNELS -ge 2 ] && echo 10 || echo 0))
# GA4 CVR score (0-20)
GA4_CVR=$(echo "$GA4_DATA" | jq -r '.cvr // "0"' 2>/dev/null || echo "0")
CVR_SCORE=$(awk "BEGIN { c = ${GA4_CVR:-0}; if (c >= 2) print 20; else if (c >= 1) print 10; else print 0 }")
# SEO clicks score (0-10)
GSC_CLICKS=$(echo "$GSC_DATA" | jq -r '.clicks // 0' 2>/dev/null || echo "0")
SEO_SCORE=$(awk "BEGIN { c = ${GSC_CLICKS:-0}; if (c >= 1000) print 10; else if (c >= 100) print 5; else print 0 }")
HEALTH_SCORE=$((ROAS_SCORE + EMAIL_SCORE + DIV_SCORE + CVR_SCORE + SEO_SCORE))
HEALTH_STATUS="Critical"
[ $HEALTH_SCORE -ge 40 ] && HEALTH_STATUS="Warning"
[ $HEALTH_SCORE -ge 70 ] && HEALTH_STATUS="Healthy"

# Emit unified JSON
jq -n \
  --arg project "$PROJECT" \
  --argjson klaviyo "$KLAVIYO_DATA" \
  --argjson meta "$META_DATA" \
  --argjson ga4 "$GA4_DATA" \
  --argjson gsc "$GSC_DATA" \
  --argjson google_ads "$GADS_DATA" \
  --argjson instagram "$INSTAGRAM_DATA" \
  --arg blended_roas "$BLENDED_ROAS" \
  --argjson health_score "$HEALTH_SCORE" \
  --arg health_status "$HEALTH_STATUS" \
  --arg date "$TODAY" \
  '{date: $date, project: (if $project == "" then null else $project end), klaviyo: $klaviyo, meta: $meta, ga4: $ga4, gsc: $gsc, google_ads: $google_ads, instagram: $instagram, blended_roas: $blended_roas, health_score: $health_score, health_status: $health_status}'
