-- FUNCTION: trans.apply_stock_movement(text, text, text, text, text, date, text, numeric, text, text, uuid, text)

-- DROP FUNCTION IF EXISTS trans.apply_stock_movement(text, text, text, text, text, date, text, numeric, text, text, uuid, text);

CREATE OR REPLACE FUNCTION trans.apply_stock_movement(
	p_merchant_id text,
	p_warehouse_id text,
	p_sku text,
	p_batch_no text,
	p_catalogue_id text,
	p_expiry_date date,
	p_uom text,
	p_qty numeric,
	p_txn_type text,
	p_ref_type text,
	p_ref_id uuid,
	p_user text)
    RETURNS void
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE PARALLEL UNSAFE
AS $BODY$
DECLARE
    v_ledger_id uuid := gen_random_uuid();
    v_qty_change numeric;
BEGIN
    ----------------------------------------------------------------
    -- Idempotency check
    ----------------------------------------------------------------
    IF EXISTS (
        SELECT 1
        FROM trans.scm_stock_ledger
        WHERE ref_type = p_ref_type
          AND ref_id   = p_ref_id
          AND sku      = p_sku
          AND batch_no = p_batch_no
    ) THEN
        RETURN;
    END IF;

    ----------------------------------------------------------------
    -- Determine quantity change based on transaction type
    ----------------------------------------------------------------
    CASE p_txn_type
        WHEN 'GRN_IN' THEN
            v_qty_change := p_qty;  -- Add stock
        WHEN 'ADJUST_IN' THEN
            v_qty_change := p_qty;  -- Add stock
        WHEN 'RETURN_IN' THEN
            v_qty_change := p_qty;  -- Add stock
        WHEN 'TRANSFER_IN' THEN
            v_qty_change := p_qty;  -- Add stock
        WHEN 'ADJUST_OUT' THEN
            v_qty_change := -p_qty; -- Subtract stock (negate the positive qty)
        WHEN 'SALE_OUT' THEN
            v_qty_change := -p_qty; -- Subtract stock
        WHEN 'TRANSFER_OUT' THEN
            v_qty_change := -p_qty; -- Subtract stock
        ELSE
            RAISE EXCEPTION 'Unknown transaction type: %', p_txn_type;
    END CASE;

	Raise Notice 'in';
    RAISE NOTICE 'Transaction type: %, Input qty: %, Calculated change: %', 
        p_txn_type, p_qty, v_qty_change;
    
    RAISE NOTICE 'Inserting ledger: %, %, %, %, %, %, %, %, %, %, %',
        v_ledger_id,
        p_merchant_id,
        p_warehouse_id,
        p_sku,
        p_batch_no,
        p_txn_type,
        v_qty_change,  -- Store the calculated change in ledger
        p_ref_type,
        p_ref_id,
        p_user,
        NOW();
        
    ----------------------------------------------------------------
    -- Ledger insert (store the ACTUAL qty change with proper sign)
    ----------------------------------------------------------------
    INSERT INTO trans.scm_stock_ledger (
        ledger_id,
        merchant_id,
        warehouse_id,
        sku,
        batch_no,
        txn_type,
        qty,
        ref_type,
        ref_id,
        created_by,
        created_at
    ) VALUES (
        v_ledger_id,
        p_merchant_id,
        p_warehouse_id,
        p_sku,
        p_batch_no,
        p_txn_type,
        v_qty_change,  -- Store with correct sign
        p_ref_type,
        p_ref_id,
        p_user,
        NOW()
    );
    
    RAISE NOTICE 'Stock ledger done';
    
    ----------------------------------------------------------------
    -- Stock snapshot upsert (ALL TABLE COLUMNS)
    ----------------------------------------------------------------
    INSERT INTO trans.scm_stock (
        merchant_id,
        warehouse_id,
        sku,
        batch_no,
        catalogue_id,
        uom,
        qty_on_hand,
        qty_reserved,
        qty_available,
        cost_price,
        expiry_date,
        ledger_id,
        created_at,
        updated_at
    ) VALUES (
        p_merchant_id,
        p_warehouse_id,
        p_sku,
        p_batch_no,
        p_catalogue_id,
        p_uom,
        GREATEST(v_qty_change, 0),  -- Use calculated change (don't allow negative on insert)
        0,                           -- qty_reserved
        GREATEST(v_qty_change, 0),  -- qty_available
        NULL,                        -- cost_price
        p_expiry_date,              -- expiry_date
        v_ledger_id,
        NOW(),
        NOW()
    )
    ON CONFLICT (merchant_id, warehouse_id, catalogue_id, batch_no)
    DO UPDATE SET
        qty_on_hand   = GREATEST(trans.scm_stock.qty_on_hand + v_qty_change, 0),
        qty_available = GREATEST((trans.scm_stock.qty_on_hand + v_qty_change) - trans.scm_stock.qty_reserved, 0),
        ledger_id     = v_ledger_id,
        updated_at    = NOW();
        
    RAISE NOTICE 'Stock updated. Final qty change applied: %', v_qty_change;
END;
$BODY$;

ALTER FUNCTION trans.apply_stock_movement(text, text, text, text, text, date, text, numeric, text, text, uuid, text)
    OWNER TO trans_owner;
