WITH
-- 1️⃣ Daily close with previous close and daily % change
daily_prev AS (
  SELECT
    UPPER(Ticker) AS symbol,
    CAST(dt AS date) AS trade_date,
    close::numeric AS close,
    LAG(close) OVER (PARTITION BY Ticker ORDER BY dt) AS prev_close,
    100.0 * (close - LAG(close) OVER (PARTITION BY Ticker ORDER BY dt))
           / NULLIF(LAG(close) OVER (PARTITION BY Ticker ORDER BY dt), 0) AS daily_pct_change,
    CASE WHEN close >= LAG(close) OVER (PARTITION BY Ticker ORDER BY dt)
         THEN 'UP' ELSE 'DOWN' END AS daily_direction
  FROM price_daily
),

-- 2️⃣ Intraday prices joined with prior close and session tagging
minute_enriched AS (
  SELECT
    UPPER(m.Ticker) AS symbol,
    (m.ts AT TIME ZONE 'America/New_York') AS ts_et,
    CAST(m.ts AT TIME ZONE 'America/New_York' AS date) AS trade_date,
    m.close::numeric AS close,
    dp.prev_close,
    100.0 * (m.close - dp.prev_close) / NULLIF(dp.prev_close,0) AS pct_from_prev_close,
    CASE
      WHEN CAST(m.ts AT TIME ZONE 'America/New_York' AS time) <  TIME '09:30' THEN 'PRE'
      WHEN CAST(m.ts AT TIME ZONE 'America/New_York' AS time) >= TIME '16:00' THEN 'POST'
      ELSE 'RTH'
    END AS session
  FROM price_1m m
  JOIN daily_prev dp
    ON dp.symbol = UPPER(m.Ticker)
   AND dp.trade_date = CAST(m.ts AT TIME ZONE 'America/New_York' AS date)
  WHERE dp.prev_close IS NOT NULL
),

-- 3️⃣ First ±3% cross per day
first_cross AS (
  SELECT DISTINCT ON (symbol, trade_date)
    symbol,
    trade_date,
    ts_et AS first_cross_ts,
    CASE WHEN pct_from_prev_close >= 3 THEN 'UP' ELSE 'DOWN' END AS first_cross_direction,
    pct_from_prev_close AS first_cross_pct,
    session AS first_cross_session
  FROM minute_enriched
  WHERE ABS(pct_from_prev_close) >= 3
  ORDER BY symbol, trade_date, ts_et
),

-- 4️⃣ Session peaks
session_peaks AS (
  SELECT
    symbol, trade_date,
    MAX(ABS(pct_from_prev_close)) FILTER (WHERE session='PRE')  AS max_abs_pct_pre,
    MAX(ABS(pct_from_prev_close)) FILTER (WHERE session='RTH')  AS max_abs_pct_rth,
    MAX(ABS(pct_from_prev_close)) FILTER (WHERE session='POST') AS max_abs_pct_post
  FROM minute_enriched
  GROUP BY symbol, trade_date
),

-- 5️⃣ AlertStream aggregation
alerts_pre AS (
  SELECT
    UPPER(a."Ticker") AS symbol,
    a."Timestamp"::timestamp AS alert_ts_raw,
    a."Type",
    a."Message"
  FROM public."AlertStream_monthly" a
),
alert_agg AS (
  SELECT
    symbol,
    CAST(alert_ts_raw AT TIME ZONE 'America/New_York' AS date) AS trade_date,
    COUNT(*) AS alert_count,
    SUM(CASE WHEN "Type" ILIKE '%AnnualHigh%' THEN 1 ELSE 0 END) AS alert_52w_high,
    SUM(CASE WHEN "Type" ILIKE '%AnnualLow%'  THEN 1 ELSE 0 END) AS alert_52w_low,
    SUM(CASE WHEN "Type" ILIKE '%PriceSpike%' THEN 1 ELSE 0 END) AS alert_price_spike,
    SUM(CASE WHEN "Type" ILIKE '%DarkPool%'   THEN 1 ELSE 0 END) AS alert_darkpool,
    SUM(CASE WHEN "Type" ILIKE '%Block%'      THEN 1 ELSE 0 END) AS alert_block,
    SUM(CASE WHEN "Type" ILIKE '%Halt%'       THEN 1 ELSE 0 END) AS alert_halt,
    SUM(CASE WHEN "Type" ILIKE '%Options%'    THEN 1 ELSE 0 END) AS alert_options,
    SUM(CASE WHEN "Message" ~* '(earn(ing|ings|ed|s)|\\bEPS\\b|guidance)' THEN 1 ELSE 0 END) AS news_earnings,
    SUM(CASE WHEN "Message" ~* '(merger|acquir|M&A|takeover)' THEN 1 ELSE 0 END) AS news_mergers,
    SUM(CASE WHEN "Message" ~* '\\b(FDA|PDUFA)\\b|trial|phase\\s?(1|2|3)|endpoint' THEN 1 ELSE 0 END) AS news_fda,
    SUM(CASE WHEN "Message" ~* '(buyback|repurchase|\\bASR\\b)' THEN 1 ELSE 0 END) AS news_buyback,
    SUM(CASE WHEN "Message" ~* 'dividend|ex[- ]?div' THEN 1 ELSE 0 END) AS news_dividend,
    SUM(CASE WHEN "Message" ~* '(^|\\W)split(\\W|$)|reverse\\s+split' THEN 1 ELSE 0 END) AS news_split,
    SUM(CASE WHEN "Message" ~* '(contract|award|supplier|customer)' THEN 1 ELSE 0 END) AS news_contract,
    SUM(CASE WHEN "Message" ~* '(8-K|10-Q|10-K|S-1|\\bSEC\\b)' THEN 1 ELSE 0 END) AS news_sec,
    SUM(CASE WHEN "Message" ~* '(upgrade|raised\\s+to|target\\s+raise)' THEN 1 ELSE 0 END) AS news_rating_up,
    SUM(CASE WHEN "Message" ~* '(downgrade|lowered\\s+to|target\\s+cut)' THEN 1 ELSE 0 END) AS news_rating_dn
  FROM alerts_pre
  GROUP BY 1,2
),

-- 6️⃣ OptionsFlow aggregation
options_pre AS (
  SELECT
    UPPER(o."Symbol") AS symbol,
    to_timestamp(o."CreatedDate" || ' ' || o."CreatedTime", 'MM/DD/YYYY HH12:MI:SS AM') AS opt_ts_raw,
    o.*
  FROM public."OptionsFlow_monthly" o
),
options_agg AS (
  SELECT
    symbol,
    CAST(opt_ts_raw AT TIME ZONE 'America/New_York' AS date) AS trade_date,
    COUNT(*) AS opt_trades,
    SUM(COALESCE("Premium", "Price"*"Volume"*100.0)) AS opt_notional_total,
    SUM(CASE
          WHEN ("Color" ILIKE '%BULL%')
            OR (UPPER("CallPut")='CALL' AND UPPER("Side") IN ('B','BUY'))
            OR (UPPER("CallPut")='PUT'  AND UPPER("Side") IN ('S','SELL'))
          THEN COALESCE("Premium","Price"*"Volume"*100.0)
          ELSE 0 END) AS opt_notional_bull,
    SUM(CASE
          WHEN ("Color" ILIKE '%BEAR%')
            OR (UPPER("CallPut")='PUT'  AND UPPER("Side") IN ('B','BUY'))
            OR (UPPER("CallPut")='CALL' AND UPPER("Side") IN ('S','SELL'))
          THEN COALESCE("Premium","Price"*"Volume"*100.0)
          ELSE 0 END) AS opt_notional_bear,
    SUM(CASE WHEN UPPER("Type") LIKE '%SWEEP%' THEN 1 ELSE 0 END) AS opt_sweep_count,
    SUM(CASE WHEN UPPER("Type") LIKE '%BLOCK%' THEN 1 ELSE 0 END) AS opt_block_count,
    SUM(CASE WHEN COALESCE("Uoa",'F') ILIKE 'T' THEN 1 ELSE 0 END) AS opt_uoa_count,
    AVG(NULLIF("Dte",0)) AS opt_avg_dte,
    AVG(NULLIF("ImpliedVolatility",0)) AS opt_avg_iv,
    SUM(CASE WHEN UPPER("CallPut")='CALL' THEN 1 ELSE 0 END) AS opt_call_trades,
    SUM(CASE WHEN UPPER("CallPut")='PUT'  THEN 1 ELSE 0 END) AS opt_put_trades
  FROM options_pre
  GROUP BY 1,2
),

-- 7️⃣ Combine everything
final AS (
  SELECT
    dp.symbol,
    dp.trade_date,
    dp.prev_close,
    dp.close,
    dp.daily_pct_change,
    dp.daily_direction,
    fc.first_cross_ts,
    fc.first_cross_direction,
    fc.first_cross_pct,
    fc.first_cross_session,
    sp.max_abs_pct_pre,
    sp.max_abs_pct_rth,
    sp.max_abs_pct_post,
    COALESCE(al.alert_count,0) AS alert_count,
    COALESCE(al.alert_52w_high,0) AS alert_52w_high,
    COALESCE(al.alert_52w_low,0) AS alert_52w_low,
    COALESCE(al.alert_price_spike,0) AS alert_price_spike,
    COALESCE(al.alert_darkpool,0) AS alert_darkpool,
    COALESCE(al.alert_block,0) AS alert_block,
    COALESCE(al.alert_halt,0) AS alert_halt,
    COALESCE(al.alert_options,0) AS alert_options,
    COALESCE(al.news_earnings,0) AS news_earnings,
    COALESCE(al.news_mergers,0) AS news_mergers,
    COALESCE(al.news_fda,0) AS news_fda,
    COALESCE(al.news_buyback,0) AS news_buyback,
    COALESCE(al.news_dividend,0) AS news_dividend,
    COALESCE(al.news_split,0) AS news_split,
    COALESCE(al.news_contract,0) AS news_contract,
    COALESCE(al.news_sec,0) AS news_sec,
    COALESCE(al.news_rating_up,0) AS news_rating_up,
    COALESCE(al.news_rating_dn,0) AS news_rating_dn,
    COALESCE(op.opt_trades,0) AS opt_trades,
    COALESCE(op.opt_notional_total,0) AS opt_notional_total,
    COALESCE(op.opt_notional_bull,0) AS opt_notional_bull,
    COALESCE(op.opt_notional_bear,0) AS opt_notional_bear,
    COALESCE(op.opt_sweep_count,0) AS opt_sweep_count,
    COALESCE(op.opt_block_count,0) AS opt_block_count,
    COALESCE(op.opt_uoa_count,0) AS opt_uoa_count,
    CASE WHEN COALESCE(al.news_earnings,0)
           +COALESCE(al.news_mergers,0)
           +COALESCE(al.news_fda,0)
           +COALESCE(al.news_buyback,0)
           +COALESCE(al.news_dividend,0)
           +COALESCE(al.news_split,0)
           +COALESCE(al.news_contract,0)
           +COALESCE(al.news_sec,0)
           +COALESCE(al.news_rating_up,0)
           +COALESCE(al.news_rating_dn,0) > 0 THEN 1 ELSE 0 END AS clue_news,
    CASE WHEN COALESCE(op.opt_notional_bull,0) > COALESCE(op.opt_notional_bear,0) THEN 1 ELSE 0 END AS clue_options_bullish,
    CASE WHEN COALESCE(op.opt_notional_bear,0) > COALESCE(op.opt_notional_bull,0) THEN 1 ELSE 0 END AS clue_options_bearish,
    CASE WHEN COALESCE(al.alert_halt,0)>0 OR COALESCE(al.alert_price_spike,0)>0 THEN 1 ELSE 0 END AS clue_halt_or_spike,
    CASE WHEN COALESCE(al.alert_52w_high,0)>0 OR COALESCE(al.alert_52w_low,0)>0 THEN 1 ELSE 0 END AS clue_52w_extreme,
    CASE WHEN COALESCE(al.alert_darkpool,0)>0 OR COALESCE(al.alert_block,0)>0 OR COALESCE(op.opt_block_count,0)>0 THEN 1 ELSE 0 END AS clue_darkpool_block,
    CASE WHEN COALESCE(op.opt_uoa_count,0)>0 THEN 1 ELSE 0 END AS clue_uoa
  FROM daily_prev dp
  LEFT JOIN first_cross fc ON fc.symbol=dp.symbol AND fc.trade_date=dp.trade_date
  LEFT JOIN session_peaks sp ON sp.symbol=dp.symbol AND sp.trade_date=dp.trade_date
  LEFT JOIN alert_agg al ON al.symbol=dp.symbol AND al.trade_date=dp.trade_date
  LEFT JOIN options_agg op ON op.symbol=dp.symbol AND op.trade_date=dp.trade_date
)
SELECT *
FROM final
ORDER BY trade_date DESC, symbol;
