-- Batch cleanup of expired timers
-- KEYS[1]: Timer index key (sorted set)
-- KEYS[2]: Timer stats key
-- KEYS[3]: Audit log stream key
-- ARGV[1]: Current timestamp
-- ARGV[2]: Batch size limit
-- ARGV[3]: Max cleanup time in milliseconds

local index_key = KEYS[1]
local stats_key = KEYS[2]
local audit_key = KEYS[3]

local current_time = tonumber(ARGV[1])
local batch_limit = tonumber(ARGV[2]) or 100
local max_time_ms = tonumber(ARGV[3]) or 1000

local start_time = redis.call('TIME')[1] * 1000 + redis.call('TIME')[2] / 1000
local cleaned_count = 0

-- Get expired timer keys (score less than current time)
local expired_keys = redis.call('ZRANGEBYSCORE', index_key, '-inf', current_time, 'LIMIT', 0, batch_limit)

for i, timer_key in ipairs(expired_keys) do
    -- Check if we've exceeded time limit
    local current_time_ms = redis.call('TIME')[1] * 1000 + redis.call('TIME')[2] / 1000
    if (current_time_ms - start_time) > max_time_ms then
        break
    end
    
    -- Check if timer still exists and is actually expired
    local ttl = redis.call('TTL', timer_key)
    if ttl == -2 or ttl == 0 then
        -- Timer has expired, remove from index
        redis.call('ZREM', index_key, timer_key)
        cleaned_count = cleaned_count + 1
        
        -- Add to audit log
        redis.call('XADD', audit_key, '*',
            'event', 'timer_expired_cleanup',
            'timer_key', timer_key,
            'cleanup_timestamp', current_time
        )
    elseif ttl == -1 then
        -- Timer exists but has no TTL, check if it should be removed
        local timer_data = redis.call('GET', timer_key)
        if timer_data then
            -- Parse expiration time from data and compare
            -- This is a simplified check - in production you'd parse JSON properly
            redis.call('ZREM', index_key, timer_key)
        end
    end
end

-- Update cleanup statistics
redis.call('HINCRBY', stats_key, 'cleanup_runs', 1)
redis.call('HINCRBY', stats_key, 'cleaned_timers', cleaned_count)
redis.call('HSET', stats_key, 'last_cleanup', current_time)

-- Publish cleanup notification
redis.call('PUBLISH', 'timer_events', 
    string.format('{"event":"batch_cleanup","cleaned_count":%d,"timestamp":%d}', 
                  cleaned_count, current_time))

return {cleaned_count = cleaned_count, remaining_expired = #expired_keys - cleaned_count}