-- Guard: core code must not call love loaders directly on literal
-- assets/generated paths.  Centralized loading (Assets / the NX overlay)
-- is what keeps mod overrides and the Blue/Yellow NX fallback working; a
-- raw literal load silently bypasses both.  This scans every src/*.lua and
-- fails on new violations so the class of bug cannot regress by accident.
-- Self-contained: luajit tests/engine/nx_generated_guard_test.lua
package.path = "./?.lua;./?/init.lua;" .. package.path

local T = require("tests.harness")
local check = T.check

local FORBIDDEN = {
  'love%.graphics%.newImage%(%s*"assets/generated',
  'love%.image%.newImageData%(%s*"assets/generated',
  'love%.audio%.newSource%(%s*"assets/generated',
  'love%.sound%.newSoundData%(%s*"assets/generated',
  'love%.graphics%.newFont%(%s*"assets/generated',
  'love%.font%.newFontData%(%s*"assets/generated',
  'love%.filesystem%.read%(%s*"assets/generated',
  'love%.filesystem%.load%(%s*"assets/generated',
  'love%.filesystem%.lines%(%s*"assets/generated',
  'love%.filesystem%.newFileData%(%s*"assets/generated',
  'love%.filesystem%.getInfo%(%s*"assets/generated',
}

-- Files that legitimately reference generated literals but never load them
-- directly (writers, mount setup, the NX probe, mod source roots) are not
-- matched by the patterns above, so no allowlist is needed.

local function listLuaFiles(dir, out)
  out = out or {}
  local p = io.popen('find "' .. dir .. '" -name "*.lua" -type f')
  if not p then return out end
  for line in p:lines() do
    out[#out + 1] = line
  end
  p:close()
  return out
end

local violations = {}
for _, file in ipairs(listLuaFiles("src")) do
  local f = io.open(file, "r")
  if f then
    local body = f:read("*a")
    f:close()
    for _, pat in ipairs(FORBIDDEN) do
      if body:find(pat) then
        violations[#violations + 1] = file .. " matches " .. pat
      end
    end
  end
end

check(#violations == 0,
  "no direct love loader call on literal assets/generated paths"
    .. (#violations > 0 and (":\n  " .. table.concat(violations, "\n  ")) or ""))

-- The NX overlay module itself must exist and stay NX-gated at install time.
local f = io.open("main.lua", "r")
local mainSrc = f and f:read("*a") or ""
if f then f:close() end
check(mainSrc:find("NxAssetOverlay", 1, true) ~= nil,
  "main.lua installs NxAssetOverlay")
check(mainSrc:find("isNX", 1, true) ~= nil
    and mainSrc:find('require("src.core.NxAssetOverlay").install()', 1, true) ~= nil,
  "the overlay install stays gated on Platform.isNX()")

-- Gold Game2 / World must compile data/generated via CacheFs.loadActive so
-- a fused NX boot does not depend on mounting gold/ onto data/generated.
local function readSrc(path)
  local fh = io.open(path, "r")
  local body = fh and fh:read("*a") or ""
  if fh then fh:close() end
  return body
end
local game2Src = readSrc("src/core/Game2.lua")
check(game2Src:find("loadActive", 1, true) ~= nil,
  "Game2 compiles generated modules through CacheFs.loadActive")
check(game2Src:find("loadActive(path)", 1, true) ~= nil,
  "Game2.loadGenerated calls loadActive")
local worldSrc = readSrc("src/world/gen2/World.lua")
check(worldSrc:find("loadActive", 1, true) ~= nil,
  "World's on-disk fallback also uses CacheFs.loadActive")

T.finish()
