-- Promote timers between tiers based on time-to-execution
-- KEYS[1]: Source tier index (e.g., "tier_2_index")
-- KEYS[2]: Destination tier index (e.g., "tier_1_index") 
-- KEYS[3]: Timer stats key
-- ARGV[1]: Current timestamp
-- ARGV[2]: Promotion threshold (seconds before execution)
-- ARGV[3]: Batch size limit
-- ARGV[4]: Source tier number
-- ARGV[5]: Destination tier number

local source_index = KEYS[1]
local dest_index = KEYS[2]
local stats_key = KEYS[3]

local current_time = tonumber(ARGV[1])
local promotion_threshold = tonumber(ARGV[2])
local batch_limit = tonumber(ARGV[3]) or 50
local source_tier = tonumber(ARGV[4])
local dest_tier = tonumber(ARGV[5])

local promotion_time = current_time + promotion_threshold
local promoted_count = 0

-- Get timers that should be promoted (score <= promotion_time)
local candidates = redis.call('ZRANGEBYSCORE', source_index, '-inf', promotion_time, 'LIMIT', 0, batch_limit)

for i, timer_key in ipairs(candidates) do
    -- Verify timer still exists
    local timer_data = redis.call('GET', timer_key)
    if timer_data then
        -- Move from source to destination tier index
        local score = redis.call('ZSCORE', source_index, timer_key)
        if score then
            redis.call('ZREM', source_index, timer_key)
            redis.call('ZADD', dest_index, score, timer_key)
            promoted_count = promoted_count + 1
            
            -- Update timer data to reflect new tier
            local updated_data = string.gsub(timer_data, '"tier"%s*:%s*%d+', '"tier":' .. dest_tier)
            local ttl = redis.call('TTL', timer_key)
            if ttl > 0 then
                redis.call('SETEX', timer_key, ttl, updated_data)
            else
                redis.call('SET', timer_key, updated_data)
            end
        end
    else
        -- Timer no longer exists, remove from index
        redis.call('ZREM', source_index, timer_key)
    end
end

-- Update tier statistics
redis.call('HINCRBY', stats_key, 'tier_' .. source_tier .. '_count', -promoted_count)
redis.call('HINCRBY', stats_key, 'tier_' .. dest_tier .. '_count', promoted_count)
redis.call('HINCRBY', stats_key, 'promotion_count', promoted_count)
redis.call('HSET', stats_key, 'last_promotion', current_time)

-- Publish promotion notification
redis.call('PUBLISH', 'timer_events', 
    string.format('{"event":"timer_promotion","from_tier":%d,"to_tier":%d,"count":%d,"timestamp":%d}', 
                  source_tier, dest_tier, promoted_count, current_time))

return {
    promoted_count = promoted_count,
    source_tier = source_tier,
    dest_tier = dest_tier,
    threshold_seconds = promotion_threshold
}