// rl_min_hold_check.cu — ISV-driven minimum hold time.
//
// Overrides closing actions (a3/a4/a9/a10) to Hold (a2) when the
// current position has been held for fewer than min_hold steps.
// Hard constraint — the agent cannot exit before the minimum.
//
// Runs AFTER action selection, BEFORE trail_stop_check (which can
// still force-exit on genuine stop-loss breaches regardless of
// hold time — safety overrides patience).
//
// Per `feedback_no_atomicadd`: per-batch element-wise.
// Per `feedback_cpu_is_read_only`: pure device-side.

#include <stdint.h>

#define ACTION_HOLD               2
#define ACTION_FLAT_FROM_LONG     3
#define ACTION_FLAT_FROM_SHORT    4
#define ACTION_HALF_FLAT_LONG     9
#define ACTION_HALF_FLAT_SHORT    10
#define RL_MIN_HOLD_STEPS_INDEX   536
#define RL_HEAT_CAP_MAX_LOTS_INDEX 504

extern "C" __global__ void rl_min_hold_check(
    int*                 __restrict__ actions,          // [B] IN/OUT
    const int*           __restrict__ steps_since_done, // [B]
    const unsigned char* __restrict__ pos_state,        // [B × pos_bytes]
    const float*         __restrict__ isv,
    int                                b_size,
    int                                pos_bytes
) {
    const int b = blockIdx.x * blockDim.x + threadIdx.x;
    if (b >= b_size) return;

    const int min_hold = (int)isv[RL_MIN_HOLD_STEPS_INDEX];
    if (min_hold <= 0) return;

    const int hold = steps_since_done[b];
    if (hold >= min_hold) return;

    // Exempt positions at or above heat cap — safety exits must not
    // be blocked by min-hold (the heat cap is the last defense).
    const int position_lots = *(const int*)(pos_state + b * pos_bytes);
    const int cap = (int)isv[RL_HEAT_CAP_MAX_LOTS_INDEX];
    if (cap > 0 && (position_lots >= cap || position_lots <= -cap)) return;

    const int action = actions[b];
    if (action == ACTION_FLAT_FROM_LONG  ||
        action == ACTION_FLAT_FROM_SHORT ||
        action == ACTION_HALF_FLAT_LONG  ||
        action == ACTION_HALF_FLAT_SHORT) {
        actions[b] = ACTION_HOLD;
    }
}
