#!/bin/bash
# Nightly refresh of seap materialized views.
# Run from satra cron at 04:00 — peak DB idle window.
#
# Sources DATABASE_URL via Infisical Machine Identity (same as the
# vreaudigital container). Never echoes the value.

set -euo pipefail

LOG=/var/log/vreaudigital-mvs.log
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG"; }

log "=== Materialized view refresh started ==="

if [ ! -f /opt/vreaudigital/.infisical-mi ]; then
  log "FATAL: /opt/vreaudigital/.infisical-mi missing"
  exit 1
fi

# shellcheck disable=SC1091
source /opt/vreaudigital/.infisical-mi

TOKEN=$(infisical login \
  --method=universal-auth \
  --domain="$INFISICAL_API_URL" \
  --client-id="$INFISICAL_CLIENT_ID" \
  --client-secret="$INFISICAL_CLIENT_SECRET" \
  --silent --plain)

DATABASE_URL=$(infisical run \
  --domain="$INFISICAL_API_URL" \
  --projectId="$INFISICAL_PROJECT_ID" \
  --env="$INFISICAL_ENV" \
  --path="$INFISICAL_PATH" \
  --silent --token="$TOKEN" \
  -- sh -c 'echo "$DATABASE_URL"')

# Parse URL into PG* env vars and discard URL — psql with the URL on the command
# line leaks the password to anyone running `ps aux` (incident 2026-05-07).
DB=$(echo "$DATABASE_URL" | sed -E 's/[?&]schema=[^&]*//; s/\?$//')
export PGUSER=$(echo "$DB" | sed -E 's|^postgresql://([^:]+):.*|\1|')
export PGPASSWORD=$(echo "$DB" | sed -E 's|^postgresql://[^:]+:([^@]+)@.*|\1|')
export PGHOST=$(echo "$DB" | sed -E 's|^postgresql://[^@]+@([^:/]+).*|\1|')
export PGPORT=$(echo "$DB" | sed -E 's|^postgresql://[^@]+@[^:]+:([0-9]+)/.*|\1|')
export PGDATABASE=$(echo "$DB" | sed -E 's|^postgresql://[^@]+@[^/]+/([^?]+).*|\1|')
unset DATABASE_URL TOKEN DB

START=$(date +%s)
psql -v ON_ERROR_STOP=1 <<'SQL' 2>&1 | tee -a "$LOG"
\timing on
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.uat_procurement_stats;
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.uat_kpi;
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_authority_concentration;
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_cpv_median_value;
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_top_cpv_divisions;
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_top_suppliers;
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_top_authorities;
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_recurrent_pairs;
REFRESH MATERIALIZED VIEW CONCURRENTLY seap.mv_supplier_cpv_share;
-- Cross-source MVs (added 2026-05-11 after backfills)
REFRESH MATERIALIZED VIEW CONCURRENTLY cnsc.mv_per_authority_cui;
REFRESH MATERIALIZED VIEW CONCURRENTLY cnsc.mv_per_contestator_cui;
REFRESH MATERIALIZED VIEW CONCURRENTLY anre.mv_licente_per_cui;
REFRESH MATERIALIZED VIEW CONCURRENTLY ancom.mv_operatori_per_cui;
REFRESH MATERIALIZED VIEW CONCURRENTLY asf.mv_entitati_per_cui;
REFRESH MATERIALIZED VIEW CONCURRENTLY aaas.mv_per_cui;
-- Red-flags KPI snapshot (043_red_flags_kpi_snapshot.sql)
SELECT public_kpi.refresh_red_flags_counts();
-- Red-flags previews snapshot (044_red_flags_previews_snapshot.sql) — top-5
-- rows per recipe; landing reads as a single SELECT instead of awaiting 14
-- live cross-source queries (~17s → ~5ms).
SELECT public_kpi.refresh_red_flags_previews();
-- Cauta default-browse facets+totals snapshot (046) — short-circuits the 6
-- parallel facet aggregates when no filter is set (~1.9s → ~50ms).
SELECT public_kpi.refresh_cauta_defaults();
SQL
END=$(date +%s)

log "=== Done in $((END-START))s ==="
