#!/usr/bin/env python3
"""Refresh TTL on existing RAG keys to match new persistence policy."""

import subprocess
import sys


def redis_cli(*args):
    result = subprocess.run(
        ["docker", "exec", "rmi-redis", "redis-cli", "-a", REDIS_PASS, *args],
        capture_output=True,
        text=True,
    )
    return result.stdout.strip()


def redis_eval(lua_script, numkeys, *keys_and_args):
    """Run a Lua script via EVAL. Returns stdout."""
    all_args = ["EVAL", lua_script, str(numkeys), *list(keys_and_args)]
    return redis_cli(*all_args)


# Get Redis password from container env
env_out = subprocess.run(["docker", "exec", "rmi-backend", "env"], capture_output=True, text=True).stdout
REDIS_PASS = ""
for line in env_out.splitlines():
    if line.startswith("REDIS_PASSWORD="):
        REDIS_PASS = line.split("=", 1)[1]
        break

if not REDIS_PASS:
    print("ERROR: Could not find REDIS_PASSWORD")
    sys.exit(1)

# TTL policy: 0 = persist (no expiry), N = seconds
TTL_POLICY = {
    "scam_patterns": 0,  # permanent
    "contract_audits": 0,  # permanent
    "transaction_patterns": 0,  # permanent
    "forensic_reports": 0,  # permanent
    "known_scams": 0,  # permanent (was 365d)
    "wallet_profiles": 86400 * 365,  # 1 year
    "market_intel": 86400 * 365,  # 1 year
    "token_analysis": 86400 * 90,  # 90 days
    "news_articles": 86400 * 30,  # 30 days
    "general": 86400 * 30,  # 30 days
}

total_scanned = 0
total_persisted = 0
total_refreshed = 0
errors = 0

# Lua script that processes keys in batches
# For PERSIST (ttl=0): only persist keys that have a TTL (not -1)
# For EXPIRE (ttl>0): only set expiry on keys that are persistent (-1) or have shorter TTL
LUA_BATCH = """
local collection = ARGV[1]
local desired_ttl = tonumber(ARGV[2])
local count = 0
local persist_count = 0
local refresh_count = 0

-- Use SCAN to iterate keys
local cursor = '0'
repeat
    local reply = redis.call('SCAN', cursor, 'MATCH', 'rag:' .. collection .. ':*', 'COUNT', 500)
    cursor = reply[1]
    local keys = reply[2]
    for i, key in ipairs(keys) do
        count = count + 1
        local current_ttl = redis.call('TTL', key)
        if desired_ttl == 0 then
            -- Make permanent: only if not already persistent (-1)
            if current_ttl ~= -1 then
                redis.call('PERSIST', key)
                persist_count = persist_count + 1
            end
        else
            -- Set expiry if currently persistent (-1) or TTL is shorter than desired
            if current_ttl == -1 then
                -- Already persistent, leave it (don't downgrade)
            elseif current_ttl < desired_ttl then
                redis.call('EXPIRE', key, desired_ttl)
                refresh_count = refresh_count + 1
            end
        end
    end
until cursor == '0'

return {count, persist_count, refresh_count}
"""

print("Refreshing RAG TTLs according to persistence policy...")
print()

for collection, desired_ttl in TTL_POLICY.items():
    result = redis_eval(LUA_BATCH, 0, collection, str(desired_ttl))
    # Result format: one integer per line (Lua array serializes as newline-separated)
    lines = [l.strip() for l in result.splitlines() if l.strip()]  # noqa: E741
    if len(lines) == 3:
        try:
            scanned = int(lines[0].lstrip("[").rstrip(","))
            persisted = int(lines[1].rstrip(","))
            refreshed = int(lines[2].rstrip("]"))
        except (ValueError, IndexError):
            print(f"  {collection}: unexpected result: {result}")
            errors += 1
            continue

        action = f"TTL={0} (persistent)" if desired_ttl == 0 else f"TTL={desired_ttl}s ({desired_ttl // 86400}d)"
        print(f"  {collection}: {scanned} keys scanned, {persisted} persisted, {refreshed} refreshed [{action}]")
        total_scanned += scanned
        total_persisted += persisted
        total_refreshed += refreshed
    else:
        print(f"  {collection}: unexpected result: {result}")
        errors += 1

print()
print(
    f"Done: {total_scanned} keys scanned, {total_persisted} persisted (TTL removed), {total_refreshed} TTLs refreshed"
)
if errors:
    print(f"Errors: {errors}")
