-- @author DoomTero 2026
-- @copyright 2026 DoomTero - ZomboRut original work. ref:ab4a2088
-- @license Proprietary. Not licensed for reuse, redistribution or derivative works without written permission from DoomTero. Ask - permission is obtainable. See ZomboRut/LICENSE.txt

local ZomboRutScene = require "ZomboRut/ZomboRutScene"

local SUBDUED_SCENES = {
	{ base = "Sex_SubdueCowgirl"   },
	{ base = "Sex_SubdueDoggy"     },
	{ base = "Sex_SubdueMissionary"},
	{ base = "Drag_Subdue"       },
	{ base             = "Drag_Subdue",
	  labelOverride    = "[DEBUG] Drag Legs (auto-walk test)",
	  debugOnly        = true,
	  autoWalkOverride = true },
}

local function isSubduedZombie(obj)
	if not instanceof(obj, "IsoZombie") then return false end
	if obj:isDead() then return false end
	local md = obj.getModData and obj:getModData() or nil
	return md and md.zrSubdued == true
end

local findOnTilesAndNeighbors = require("ZomboRut/ContextMenu/ZR_MenuUtil").findOnTilesAndNeighbors
local setIcon = require("ZomboRut/ContextMenu/ZR_MenuUtil").icon
local sceneLabel = require("ZomboRut/ContextMenu/ZR_MenuUtil").sceneLabel

local function resolveWithSubmissiveSpoof(playerObj, target, sceneBase)
	if ZomboRutScene._sameGenderBlocked(playerObj, target) then return nil end
	if not playerObj or not playerObj.isFemale or playerObj:isFemale() then return nil end
	if not (SandboxVars and SandboxVars.ZomboRut
		and SandboxVars.ZomboRut.maleSubmissiveDefeat == true)
	then
		return nil
	end
	local zg = (target and target.isFemale and target:isFemale()) and "F" or "M"
	local spoofedId = sceneBase .. "_F" .. zg
	if ZomboRutScene.get(spoofedId) then
		return spoofedId
	end
	return nil
end

local function resolveSubduedSceneId(playerObj, target, sceneBase)
	return resolveWithSubmissiveSpoof(playerObj, target, sceneBase)
		or ZomboRutScene._resolveGender(playerObj, target, sceneBase)
end

local function launchScene(playerObj, target, sceneBase, opts)
	if not isSubduedZombie(target) then return end
	local resolvedId = resolveSubduedSceneId(playerObj, target, sceneBase)
	if not resolvedId then return end
	ZomboRutScene.playSceneFromAttacker(playerObj, target, resolvedId)
	if opts and opts.autoWalkOverride then
		local active = ZomboRutScene._active[playerObj]
		if active then
			active.ctx = active.ctx or {}
			active.ctx.autoWalkOverride = true
		end
	end
end

return function(ContextMenu, playerObj, context, worldobjects, getRoot)
	if not playerObj then return end

	if playerObj:isDraggingCorpse() then return end

	local target = findOnTilesAndNeighbors(worldobjects, "moving", isSubduedZombie)
	if not target then return end

	local debugOn = isDebugEnabled and isDebugEnabled()
	local dragEntries  = {}
	local sexEntries   = {}
	local debugEntries = {}
	for _, spec in ipairs(SUBDUED_SCENES) do
		if not (spec.debugOnly and not debugOn) then
			local resolvedId = resolveSubduedSceneId(playerObj, target, spec.base)
			if resolvedId then
				local cfg = ZomboRutScene.get(resolvedId)
				local entry = {
					base             = spec.base,
					id               = resolvedId,
					label            = spec.labelOverride or (cfg and cfg.label) or spec.base,
					autoWalkOverride = spec.autoWalkOverride,
					icon             = cfg and cfg.icon,
				}
				if spec.debugOnly then
					debugEntries[#debugEntries + 1] = entry
				elseif cfg and cfg.isUtility then
					dragEntries[#dragEntries + 1] = entry
				else
					sexEntries[#sexEntries + 1] = entry
				end
			end
		end
	end

	if #dragEntries == 0 and #sexEntries == 0 and #debugEntries == 0 then
		return
	end

	local function makeCb(entry)
		return function()
			launchScene(playerObj, target, entry.base,
				{ autoWalkOverride = entry.autoWalkOverride })
		end
	end

	local zrMenu = getRoot()

	for _, entry in ipairs(dragEntries) do
		setIcon(zrMenu:addOption(sceneLabel(entry.label), worldobjects, makeCb(entry)), entry.icon or "Drag")
	end

	if #sexEntries > 0 then
		local root = zrMenu:addOption(getText("ContextMenu_ZR_SexScenes"), worldobjects, nil)
		setIcon(root, "Scene")
		local sub  = ISContextMenu:getNew(context)
		zrMenu:addSubMenu(root, sub)
		for _, entry in ipairs(sexEntries) do
			setIcon(sub:addOption(sceneLabel(entry.label), worldobjects, makeCb(entry)), entry.icon or "Scene_Leaf")
		end
	end

	for _, entry in ipairs(debugEntries) do
		setIcon(zrMenu:addOption(sceneLabel(entry.label), worldobjects, makeCb(entry)), entry.icon or "Scene_Leaf")
	end

	if debugOn then
		local sexIds = {}
		for _, id in ipairs(ZomboRutScene.list()) do
			if type(id) == "string" and id:sub(1, 4) == "Sex_" then
				sexIds[#sexIds + 1] = id
			end
		end
		table.sort(sexIds)
		if #sexIds > 0 then
			local root = zrMenu:addOption("[DEBUG] ZR Sex Scenes", worldobjects, nil)
			setIcon(root, "Debug")
			local sub  = ISContextMenu:getNew(context)
			zrMenu:addSubMenu(root, sub)
			for _, id in ipairs(sexIds) do
				setIcon(sub:addOption(id, worldobjects, function()
					ZomboRutScene.playSceneFromAttacker(playerObj, target, id)
				end), "Scene_Leaf")
			end
		end
	end
end
