-- ============================================================
-- Migration 021: Capital Ledger Reserve Formula Parity Fix
-- Date: 2026-03-03
-- Purpose:
--   - Align fn_reserve_for_order with runtime available-capital math.
--   - Prevent false "Insufficient capital to reserve order" when realized_pnl > 0.
-- ============================================================

DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
        FROM pg_constraint
        WHERE conname = 'chk_capital_ledgers_non_negative'
    ) THEN
        ALTER TABLE capital_ledgers
            ADD CONSTRAINT chk_capital_ledgers_non_negative
            CHECK (
                allocated_capital >= 0
                AND reserved_for_orders >= 0
                AND reserved_for_positions >= 0
            );
    END IF;
END;
$$;

CREATE OR REPLACE FUNCTION fn_reserve_for_order(p_profile uuid, p_amount numeric)
RETURNS capital_ledgers AS $$
DECLARE
    ledger capital_ledgers;
BEGIN
    IF COALESCE(p_amount, 0) <= 0 THEN
        RAISE EXCEPTION 'Invalid reserve amount for profile % (amount=%)', p_profile, p_amount;
    END IF;

    UPDATE capital_ledgers
    SET reserved_for_orders = reserved_for_orders + p_amount,
        updated_at = now()
    WHERE profile_id = p_profile
      AND (allocated_capital + realized_pnl - reserved_for_orders - reserved_for_positions) >= p_amount
    RETURNING * INTO ledger;

    IF NOT FOUND THEN
        RAISE EXCEPTION 'Insufficient capital for profile %', p_profile;
    END IF;

    RETURN ledger;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
