local _, ns = ...
local SlickUI = ns.SlickUI

local GroupMarkers = {
	MarkerNames = {
		[0] = "None", [1] = "Star", [2] = "Circle", [3] = "Diamond", [4] = "Triangle",
		[5] = "Moon", [6] = "Square", [7] = "Cross", [8] = "Skull",
	},
	Assignments = {
		{ key = "tank1", label = "Tank 1", role = "TANK", order = 1 },
		{ key = "tank2", label = "Tank 2", role = "TANK", order = 2 },
		{ key = "healer1", label = "Healer 1", role = "HEALER", order = 1 },
		{ key = "healer2", label = "Healer 2", role = "HEALER", order = 2 },
		{ key = "healer3", label = "Healer 3", role = "HEALER", order = 3 },
	},
}
SlickUI.GroupMarkers = GroupMarkers

local function IsAccessible(value)
	if canaccessvalue and not canaccessvalue(value) then return false end
	if issecretvalue and issecretvalue(value) then return false end
	return value ~= nil
end

function GroupMarkers:GetMarkerLabel(marker)
	marker = tonumber(marker) or 0
	if marker <= 0 then return "None" end
	return string.format("|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_%d:16:16|t %s",
		marker, self.MarkerNames[marker] or ("Marker " .. marker))
end

function GroupMarkers:CanApply()
	if not IsInGroup() then return false, "You are not in a group." end
	if IsInRaid() and not UnitIsGroupLeader("player") and not UnitIsGroupAssistant("player") then
		return false, "Raid leader or assistant permission is required to apply group marks."
	end
	return true
end

function GroupMarkers:GetGroupUnits()
	local units = {}
	if IsInRaid() then
		for index = 1, GetNumGroupMembers() do units[#units + 1] = "raid" .. index end
	else
		units[#units + 1] = "player"
		for index = 1, GetNumSubgroupMembers() do units[#units + 1] = "party" .. index end
	end
	return units
end

function GroupMarkers:GetRoleUnits()
	local roles = { TANK = {}, HEALER = {} }
	for _, unit in ipairs(self:GetGroupUnits()) do
		if UnitExists(unit) then
			local playerOK, isPlayer = pcall(UnitIsPlayer, unit)
			if playerOK and IsAccessible(isPlayer) and isPlayer == true then
				local roleOK, role = pcall(UnitGroupRolesAssigned, unit)
				if roleOK and IsAccessible(role) and roles[role] then roles[role][#roles[role] + 1] = unit end
			end
		end
	end
	return roles
end

function GroupMarkers:RefreshSecureButtons()
	if InCombatLockdown() or not self.ApplyPanel then return false end
	local roles = self:GetRoleUnits()
	local settings = SlickUI.DB.groupMarkers
	local active = 0
	for index, assignment in ipairs(self.Assignments) do
		local button = self.ApplyButtons[index]
		local marker = tonumber(settings[assignment.key]) or 0
		local unit = roles[assignment.role][assignment.order]
		button:SetAttribute("unit", unit)
		button:SetAttribute("marker", marker)
		button:SetAttribute("action", "set")
		button:SetEnabled(marker > 0 and unit ~= nil)
		button:SetAlpha(marker > 0 and unit and 1 or 0.35)
		button.Label:SetText(assignment.label .. ": " .. self:GetMarkerLabel(marker))
		if marker > 0 and unit then active = active + 1 end
	end
	self.ApplyPanel.Status:SetText(active > 0 and "Click each enabled row to apply its marker." or "No configured role assignments are currently available.")
	return true
end

function GroupMarkers:Apply(manual)
	local allowed, reason = self:CanApply()
	if not allowed then
		if manual and reason then SlickUI:Print(reason) end
		return false
	end
	if InCombatLockdown() then
		if manual then SlickUI:Print("Group mark assignments cannot be prepared during combat.") end
		return false
	end
	self:RefreshSecureButtons()
	self.ApplyPanel:SetShown(not self.ApplyPanel:IsShown())
	return true
end

function GroupMarkers:GetWidgetText()
	return "Marks: Apply"
end

function GroupMarkers:BuildTooltip(tooltip)
	tooltip:AddLine("Group Role Marks", 1, 0.82, 0)
	tooltip:AddLine("Open secure buttons for configured tank and healer markers.", 1, 1, 1, true)
	tooltip:AddLine(" ")
	for _, assignment in ipairs(self.Assignments) do
		tooltip:AddDoubleLine(assignment.label, self:GetMarkerLabel(SlickUI.DB.groupMarkers[assignment.key]), 1, 1, 1, 1, 1, 1)
	end
end

function GroupMarkers:CreateApplyPanel()
	local panel = CreateFrame("Frame", "SlickUIRoleMarkerApplyPanel", UIParent, "BackdropTemplate")
	panel:SetSize(310, 184)
	panel:SetPoint("CENTER", UIParent, "CENTER", 0, 120)
	panel:SetFrameStrata("DIALOG")
	panel:SetClampedToScreen(true)
	panel:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8X8", edgeFile = "Interface\\Buttons\\WHITE8X8", edgeSize = 1 })
	panel:SetBackdropColor(0.035, 0.04, 0.05, 0.96)
	panel:SetBackdropBorderColor(0.55, 0.43, 0.16, 1)
	local title = panel:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	title:SetPoint("TOP", 0, -10)
	title:SetText("Apply Group Role Marks")
	local close = CreateFrame("Button", nil, panel, "UIPanelCloseButton")
	close:SetPoint("TOPRIGHT", 2, 2)
	local status = panel:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
	status:SetPoint("BOTTOM", 0, 10)
	panel.Status = status
	self.ApplyButtons = {}
	for index = 1, #self.Assignments do
		local button = CreateFrame("Button", nil, panel, "SecureActionButtonTemplate,BackdropTemplate")
		button:SetSize(280, 24)
		button:SetPoint("TOP", 0, -34 - ((index - 1) * 26))
		button:RegisterForClicks("AnyUp", "AnyDown")
		button:SetAttribute("type", "raidtarget")
		button:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8X8", edgeFile = "Interface\\Buttons\\WHITE8X8", edgeSize = 1 })
		button:SetBackdropColor(0.1, 0.11, 0.13, 1)
		button:SetBackdropBorderColor(0.3, 0.3, 0.3, 1)
		local label = button:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
		label:SetPoint("LEFT", 8, 0)
		button.Label = label
		self.ApplyButtons[index] = button
	end
	panel:Hide()
	self.ApplyPanel = panel
end

function GroupMarkers:Initialize()
	self:CreateApplyPanel()
	self.EventFrame = CreateFrame("Frame")
	for _, event in ipairs({
		"PLAYER_ENTERING_WORLD", "ZONE_CHANGED_NEW_AREA", "GROUP_ROSTER_UPDATE",
		"PLAYER_ROLES_ASSIGNED", "ROLE_CHANGED_INFORM", "PLAYER_REGEN_ENABLED",
	}) do
		self.EventFrame:RegisterEvent(event)
	end
	self.EventFrame:SetScript("OnEvent", function()
		if not InCombatLockdown() then GroupMarkers:RefreshSecureButtons() end
	end)
end

SlickUI:RegisterModule("GroupMarkers", GroupMarkers)
