/* --------- PARAMETERS --------- */
WITH params AS (
  SELECT
    interval '45 minutes'   AS lb_flow,
    interval '45 minutes'   AS lb_px,
    interval '30 minutes'   AS open_range,
    100000::numeric         AS big_prem_usd,
    0.70::numeric           AS pc_ratio_squeeze_cut,
    0.80::numeric           AS pc_ratio_bull_cut,
    0.60::numeric           AS short_vol_up_ratio,
    0.40::numeric           AS short_vol_down_ratio,
    0.004::numeric          AS up_break_pct,
    0.002::numeric          AS down_move_pct
),
clock AS (
  SELECT (now() AT TIME ZONE 'America/Chicago') AS now_cst
),

/* --------- FLOW AGGREGATION (last lb_flow) --------- */
flow AS (
  SELECT
    f."Symbol" AS symbol,
    SUM(COALESCE(NULLIF(REGEXP_REPLACE(f."Premium"::text, '[\s$,]', '', 'g'),'')::numeric, 0)) 
      FILTER (WHERE UPPER(TRIM(f."CallPut")) IN ('C','CALL','CALLS','CE') 
              AND UPPER(TRIM(f."Side")) IN ('A','AA','ASK','BUY','BOT','BTO','AT_ASK')
              AND COALESCE(NULLIF(REGEXP_REPLACE(f."Premium"::text, '[\s$,]', '', 'g'),'')::numeric, 0) >= (SELECT big_prem_usd FROM params)) AS call_prem,
    SUM(COALESCE(NULLIF(REGEXP_REPLACE(f."Premium"::text, '[\s$,]', '', 'g'),'')::numeric, 0)) 
      FILTER (WHERE UPPER(TRIM(f."CallPut")) IN ('P','PUT','PUTS','PE')
              AND UPPER(TRIM(f."Side")) IN ('A','AA','ASK','BUY','BOT','BTO','AT_ASK')
              AND COALESCE(NULLIF(REGEXP_REPLACE(f."Premium"::text, '[\s$,]', '', 'g'),'')::numeric, 0) >= (SELECT big_prem_usd FROM params)) AS put_prem,
    COUNT(*) FILTER (WHERE UPPER(TRIM(f."Side")) IN ('A','AA','ASK','BUY','BOT','BTO','AT_ASK')
                      AND COALESCE(NULLIF(REGEXP_REPLACE(f."Premium"::text, '[\s$,]', '', 'g'),'')::numeric, 0) >= (SELECT big_prem_usd FROM params)) AS big_trades,
    MAX(f."ExpirationDate") FILTER (WHERE UPPER(TRIM(f."Side")) IN ('A','AA','ASK','BUY','BOT','BTO','AT_ASK')) AS last_expiry
  FROM public."OptionsFlow_monthly" f
  CROSS JOIN clock c
  CROSS JOIN params p
  WHERE (
    CASE
      WHEN f."CreatedDate"::text ~ '^\d{4}-\d{2}-\d{2}$'
        THEN (to_timestamp(f."CreatedDate"::text || ' ' || btrim(f."CreatedTime"::text), 'YYYY-MM-DD HH12:MI AM') AT TIME ZONE 'America/Chicago')
      ELSE (to_timestamp(f."CreatedDate"::text || ' ' || btrim(f."CreatedTime"::text), 'MM/DD/YYYY HH12:MI AM') AT TIME ZONE 'America/Chicago')
    END
  ) >= c.now_cst - p.lb_flow
    AND (
    CASE
      WHEN f."CreatedDate"::text ~ '^\d{4}-\d{2}-\d{2}$'
        THEN (to_timestamp(f."CreatedDate"::text || ' ' || btrim(f."CreatedTime"::text), 'YYYY-MM-DD HH12:MI AM') AT TIME ZONE 'America/Chicago')
      ELSE (to_timestamp(f."CreatedDate"::text || ' ' || btrim(f."CreatedTime"::text), 'MM/DD/YYYY HH12:MI AM') AT TIME ZONE 'America/Chicago')
    END
  ) < c.now_cst
  GROUP BY f."Symbol"
),

/* --------- PRICE STATS (VWAP, ORH/ORL, returns) --------- */
px AS (
  SELECT
    p.symbol,
    MAX(p."timestamp") AS last_ts,
    SUM(p.close * p.volume)::numeric / NULLIF(SUM(p.volume),0) AS vwap_lb,
    (ARRAY_AGG(p.close ORDER BY p."timestamp" ASC ))[1]::numeric  AS start_px,
    (ARRAY_AGG(p.close ORDER BY p."timestamp" DESC))[1]::numeric  AS last_px,
    AVG(p.short_volume_ratio)::numeric AS short_vol_ratio
  FROM public.prices_intraday_1m p
  CROSS JOIN clock c
  CROSS JOIN params pr
  WHERE p."timestamp" >= c.now_cst - pr.lb_px
    AND p."timestamp" <  c.now_cst
  GROUP BY p.symbol
),

open_range AS (
  SELECT
    p.symbol,
    MAX(p.high) FILTER (WHERE p."timestamp" >= date_trunc('day', c.now_cst) + time '08:30'
                        AND  p."timestamp" <  date_trunc('day', c.now_cst) + time '09:00') AS or_high,
    MIN(p.low ) FILTER (WHERE p."timestamp" >= date_trunc('day', c.now_cst) + time '08:30'
                        AND  p."timestamp" <  date_trunc('day', c.now_cst) + time '09:00') AS or_low
  FROM public.prices_intraday_1m p
  CROSS JOIN clock c
  GROUP BY p.symbol
),

/* --------- COMBINE --------- */
signals AS (
  SELECT
    coalesce(f.symbol, px.symbol) AS symbol,
    f.call_prem,
    f.put_prem,
    (f.put_prem / NULLIF(f.call_prem,0))::numeric AS put_call_prem_ratio,
    f.big_trades,
    f.last_expiry,
    px.last_px,
    px.vwap_lb,
    px.start_px,
    ((px.last_px - px.start_px) / NULLIF(px.start_px,0))::numeric AS ret_lb,
    px.short_vol_ratio,
    orr.or_high,
    orr.or_low,
    CASE WHEN px.last_px > orr.or_high THEN 1 ELSE 0 END AS broke_or_high,
    CASE WHEN px.last_px > px.vwap_lb  THEN 1 ELSE 0 END AS above_vwap
  FROM flow f
  FULL OUTER JOIN px  ON px.symbol  = f.symbol
  LEFT JOIN open_range orr ON orr.symbol = COALESCE(f.symbol, px.symbol)
)

/* --------- CLASSIFICATION --------- */
SELECT
  s.symbol,
  s.last_expiry,
  ROUND(COALESCE(s.call_prem,0)::numeric, 0) AS call_prem,
  ROUND(COALESCE(s.put_prem,0)::numeric, 0)  AS put_prem,
  ROUND(100*s.ret_lb, 2) AS ret_lb_pct,
  ROUND(100*s.short_vol_ratio, 1) AS short_vol_pct,
  s.above_vwap, s.broke_or_high,
  CASE
    WHEN s.broke_or_high = 1
     AND s.above_vwap = 1
     AND s.ret_lb >= (SELECT up_break_pct FROM params)
     AND (s.put_call_prem_ratio IS NULL OR s.put_call_prem_ratio <= (SELECT pc_ratio_squeeze_cut FROM params))
    THEN 'SQUEEZE'

    WHEN s.above_vwap = 1
     AND s.ret_lb >= (SELECT up_break_pct FROM params)
     AND (s.short_vol_ratio IS NULL OR s.short_vol_ratio <= (SELECT short_vol_down_ratio FROM params))
     AND (s.put_call_prem_ratio IS NULL OR s.put_call_prem_ratio <= (SELECT pc_ratio_bull_cut FROM params))
    THEN 'UNWINDING'

    WHEN COALESCE(s.call_prem,0) > COALESCE(s.put_prem,0)
     AND s.ret_lb <= -(SELECT down_move_pct FROM params)
     AND (s.short_vol_ratio IS NULL OR s.short_vol_ratio >= (SELECT short_vol_up_ratio FROM params))
    THEN 'HEDGED SHORTING'

    WHEN COALESCE(s.call_prem,0) >= 2*COALESCE(s.put_prem,0)
     AND s.ret_lb > -(SELECT down_move_pct FROM params)
    THEN 'ACCUMULATION'

    ELSE 'NEUTRAL'
  END AS phase
FROM signals s
WHERE COALESCE(s.call_prem,0) + COALESCE(s.put_prem,0) > 0
ORDER BY
  CASE
    WHEN phase='SQUEEZE' THEN 1
    WHEN phase='UNWINDING' THEN 2
    WHEN phase='HEDGED SHORTING' THEN 3
    WHEN phase='ACCUMULATION' THEN 4
    ELSE 9
  END,
  (COALESCE(call_prem,0)+COALESCE(put_prem,0)) DESC;
