"""Lua scripts for atomic Redis operations.

All scripts follow the pattern:
- KEYS[1] = version_counter_key
- KEYS[2] = file_key (when applicable)
- ARGV = operation-specific arguments

Scripts return the version number used for the operation.
"""

# Atomically write file with new version
# KEYS: [version_counter_key, file_key]
# ARGV: [content]
# Returns: version number
WRITE_FILE = """
local v = redis.call('INCR', KEYS[1])
redis.call('HSET', KEYS[2], 'data', ARGV[1], 'version', v)
return v
"""

# Atomically append text with separator, ensuring newline
# KEYS: [version_counter_key, file_key]
# ARGV: [content, separator]
# Returns: version number
APPEND_TEXT = """
local v = redis.call('INCR', KEYS[1])
local current = redis.call('HGET', KEYS[2], 'data') or ''

-- Ensure existing content ends with newline
if current ~= '' and string.sub(current, -1) ~= '\\n' then
    current = current .. '\\n'
end

local result = current .. ARGV[2] .. ARGV[1]
redis.call('HSET', KEYS[2], 'data', result, 'version', v)
return v
"""

# Atomically append binary content (no newline handling)
# KEYS: [version_counter_key, file_key]
# ARGV: [content]
# Returns: version number
APPEND_BYTES = """
local v = redis.call('INCR', KEYS[1])
local current = redis.call('HGET', KEYS[2], 'data') or ''
local result = current .. ARGV[1]
redis.call('HSET', KEYS[2], 'data', result, 'version', v)
return v
"""

# Atomically delete path and all sub-paths (rm -rf)
# KEYS: [version_counter_key]
# ARGV: [pattern] - e.g., "prefix:/path/to/dir*" or exact key
# Returns: version number
DELETE = """
local v = redis.call('INCR', KEYS[1])
local keys = redis.call('KEYS', ARGV[1])
if #keys > 0 then
    redis.call('DEL', unpack(keys))
end
return v
"""

# Delete all files with version less than specified (bulk cleanup)
# KEYS: [version_counter_key]
# ARGV: [prefix_pattern, min_version]
# Returns: number of deleted files
BULK_CLEANUP = """
local keys = redis.call('KEYS', ARGV[1])
local deleted = 0
for _, key in ipairs(keys) do
    local ver = redis.call('HGET', key, 'version')
    if ver and tonumber(ver) < tonumber(ARGV[2]) then
        redis.call('DEL', key)
        deleted = deleted + 1
    end
end
return deleted
"""

# Read file content
# KEYS: [file_key]
# Returns: file content or nil
READ_FILE = """
return redis.call('HGET', KEYS[1], 'data')
"""

# Read file version
# KEYS: [file_key]
# Returns: version number or nil
READ_VERSION = """
return redis.call('HGET', KEYS[1], 'version')
"""

# Get current version counter
# KEYS: [version_counter_key]
# Returns: current version (0 if not set)
GET_VERSION = """
local v = redis.call('GET', KEYS[1])
return v or 0
"""
