DROP FUNCTION pricequote.build_pricing_path;

CREATE OR REPLACE FUNCTION pricequote.build_pricing_path(
  _json JSONB
)
RETURNS TABLE (
     stlc       TEXT
    ,seq        BIGINT
    ,srtcode    TEXT
    ,ds         TEXT
    ,chan       TEXT
    ,tier       TEXT
    ,vol        INT4RANGE
    ,func       TEXT
    ,val        NUMERIC
    ,price      NUMERIC
    ,math       TEXT[]
    ,lastflag   BOOLEAN
)
LANGUAGE plpgsql AS
$$
BEGIN
RETURN QUERY

WITH RECURSIVE
-- 1️⃣ Parse JSONB into rows of (entity, attr, val)
parsed AS (
  SELECT
    e.entity,
    COALESCE(e.attr, '') AS attr,
    e.val,
    e.func
  FROM jsonb_to_recordset(_json)
       AS e(entity TEXT, attr TEXT, val NUMERIC, func TEXT)
),
-- 2️⃣ Attach sequence & func from master option_sequence table
sequenced AS (
  SELECT
    p.entity,
    p.attr,
    p.val,
    p.func,
    s.DOMAIN,
    DENSE_RANK() OVER (ORDER BY s.seq) AS seq,
    ROW_NUMBER() OVER (PARTITION BY p.entity ORDER BY COALESCE(p.val,0) ASC) srt
  FROM parsed p
  JOIN pricequote.option_sequence s
    ON p.entity = s.entity
)
--select * from sequenced ORDER BY seq, srt
-- 3️⃣ Recursively accumulate pricing path
,combos AS (
  -- 🚀 Base case: first in sequence
  SELECT
    s.entity,
    s.attr,
    s.seq,
    to_char(s.srt,'FM000') srtcode,
    '' ds,
    '' chan,
    '' tier,
    null::TEXT vol,
    s.func,
    s.val,
    s.val agg,
    -- jsonb_build_array(jsonb_build_object('entity',s.entity,'attr',s.attr,'function',s.func, 'val',s.val,'seq',s.seq)) math
   ARRAY[
     CASE
       WHEN s.func = 'Price' THEN
         RPAD(s.entity || ':' || s.attr, 17, ' ') || ' + ' || LPAD(to_char(s.val, 'FM9999999990.00000'), 10, ' ')
       WHEN s.func = 'Factor' THEN
         RPAD(s.entity || ':' || s.attr, 17, ' ') || ' x ' || LPAD(to_char(s.val, 'FM9999999990.00000'), 10, ' ')
       ELSE
         RPAD(s.entity || ':' || s.attr, 17, ' ') || '   ' || LPAD(to_char(s.val, 'FM9999999990.00000'), 10, ' ')
     END
   ] math
  FROM 	
  	sequenced s
  WHERE 
  	s.seq = (SELECT MIN(x.seq) FROM sequenced x)
  UNION ALL
  -- 🔁 Recursive step: process next in sequence
  SELECT
    c.entity,
    c.attr,
    o.seq,
    c.srtcode || '.' || to_char(o.srt,'FM000'),
    c.ds || CASE WHEN o.DOMAIN = 'Product' THEN '.' || o.attr ELSE '' END ds,
    CASE WHEN o.DOMAIN = 'Channel' THEN o.attr ELSE c.chan END chan,
    CASE WHEN o.DOMAIN = 'Tier' THEN o.attr ELSE c.tier END tier,
    CASE WHEN o.DOMAIN = 'Volume' THEN o.attr ELSE c.vol END vol,
    o.func,
    o.val,
    CASE o.func WHEN 'Price' THEN c.agg + o.val WHEN 'Factor' THEN c.agg * o.val END agg,
    -- c.math || jsonb_build_array(jsonb_build_object('entity',o.entity,'attr',o.attr,'function',o.func, 'val',o.val,'seq',o.seq)) math,
    CASE WHEN (o.func = 'Price' AND o.val <> 0) OR (o.func = 'Factor' AND o.val <> 1) THEN
        c.math ||
        ARRAY[
         CASE
           WHEN o.func = 'Price' THEN
             RPAD(o.entity || ':' || o.attr, 17, ' ') || ' + ' || LPAD(to_char(o.val, 'FM9999999990.00000'), 10, ' ')
           WHEN o.func = 'Factor' THEN
             RPAD(o.entity || ':' || o.attr, 17, ' ') || ' x ' || LPAD(to_char(o.val, 'FM9999999990.00000'), 10, ' ')
           ELSE
             RPAD(o.entity || ':' || o.attr, 17, ' ') || '   ' || LPAD(to_char(o.val, 'FM9999999990.00000'), 10, ' ')
         END
       ]
    ELSE 
        c.math 
    END math
  FROM 
  	combos c
  	JOIN sequenced o ON 
  		o.seq = c.seq + 1
)
SELECT 
     -- c.entity
     c.attr
    ,c.seq
    ,c.srtcode
    ,'v1:'||SUBSTRING(c.ds,2,100) ds
    ,c.chan
    ,c.tier
    -- ,c.vol
    ,CASE
        WHEN c.vol ~ '^[0-9]+-[0-9]+$' THEN
          int4range(
            split_part(c.vol, '-', 1)::int,
            split_part(c.vol, '-', 2)::int,
            '[)'
          )
        WHEN c.vol ~ '^[0-9]+$' THEN
          int4range(
            c.vol::int,
            NULL,
            '[)'
          )
        ELSE NULL
    END AS vol
    ,c.func
    ,c.val
    ,c.agg
    ,c.math
    ,c.seq = (SELECT max(x.seq) FROM sequenced x) lastflag
FROM 
    combos c /*WHERE seq = (SELECT max(seq) FROM sequenced)*/ 
ORDER BY 
    c.srtcode ASC;

END;
$$;

/*
Anchor:EU170S50 + 0.08
Color Tier:P    x 1.30
Branding:       + 0.00
Packaging:SLV   + 0.00
Suffix:PCR      x 1.00
Accessories:    + 0.00
Channel:WHS     + 0.00
Volume:8        x 1.00
-----------------------
                  0.104
*/
