---@diagnostic disable: undefined-global

local p = {}
local Frame
local getArgs = require('Module:Arguments with aliases').getArgs
p.options = {}

local RTL = "‏"
local Categories = {
	remove = " [[تصنيف:صفحات بها وصلات للإزالة|%s]]",
	review = " [[تصنيف:وصلات إنترويكي بحاجة لمراجعة|%s]]",
	nositelinks = " [[تصنيف:صفحات بها قالب:Ill-WD2 دون وصلات لغات|%s]]",
	add = "[[تصنيف:صفحات بها وصلات إنترويكي 2|%s]]"
}

-- Utility Functions
local function isValid(value)
	return value and value ~= "" and value or nil
end

local function debug(msg)
	if isValid(p.options.debug) then
		mw.log("Module:Ill-WD2: " .. msg)
	end
end

local function countSiteLinks(id)
	local numb = 0
	local entity = mw.wikibase.getEntityObject(id)
	if entity and entity.sitelinks then
		for _ in pairs(entity.sitelinks) do
			numb = numb + 1
		end
	end

	debug("countSiteLinks(" .. id .. "): count = " .. numb)
	return numb
end

local function getSiteLink(site, qid)
	local link = mw.wikibase.sitelink(qid, site or "arwiki") or ""
	debug(("getSiteLink(site=%s): link = %s"):format(site or "arwiki", link))
	return link
end

local function labelIn(langcode)
	local label, lang = mw.wikibase.getLabelWithLang(p.options.id)
	if lang == langcode then
		return label
	end
	debug(("labelIn(%s): label = %s, lang = %s"):format(langcode, label or "", lang or ""))
	return ""
end

local function makeCategory(key)
	return (isValid(p.options.nocat) and key ~= "add") and "" or Categories[key]:format(p.options.id) or ""
end

local function extractYear(str)
	local patterns = {
		"%d%d%d%d[%–-]%d%d%d%d%s*$",
		"%d%d[%–-]%d%d%d%d%s*$",
		"%d%d%d%d[%–-]%d%d%s*$",
		"%d%d%d%d%s*$",
		"^%d%d%d%d[%–-]%d%d%d%d%s",
		"^%d%d[%–-]%d%d%d%d%s",
		"^%d%d%d%d[%–-]%d%d%s",
		"^%d%d%d%d%s"
	}

	for _, pattern in ipairs(patterns) do
		local match = mw.ustring.match(str, pattern, 1)
		if match then
			debug("extractYear: matched pattern " .. pattern)
			return match
		end
	end

	debug("extractYear: no match found")
	return str
end

local function remove_text(str, todel)
	todel = mw.text.trim(todel)
	str = mw.text.trim(str)

	-- إزالة النص من البداية
	if string.sub(str, 1, #todel) == todel then
		return string.sub(str, #todel + 1)
	end

	-- إزالة النص من النهاية
	if string.sub(str, - #todel) == todel then
		return string.sub(str, 1, #str - #todel)
	end

	-- نستخدم دالة gsub لتحل محل النص المراد حذفه بفراغ فارغ ""
	-- mw.log("remove_text: str = (" .. str .. "), todel = (" .. todel .. ")")
	return str:gsub(todel, "")
end

local function removeYear(str)
	if not isValid(p.options.noy) then
		return str
	end
	local result = str
	local year = extractYear(str)
	if year and year ~= str then
		result = remove_text(result, year)
	end

	debug(("removeYear: %s -> %s"):format(str, result))
	return result
end

local function prepareText(str)
	if isValid(p.options.text) then
		return p.options.text
	elseif isValid(p.options.year) then
		return extractYear(str)
	elseif isValid(p.options.noy) then
		return removeYear(str)
	end
	return str
end

local function makeSuffix(targetSite, targetLink, sitelinksCount)
	if sitelinksCount == 0 and not isValid(p.options.from_lua) and not isValid(p.options.wdlink) then
		return makeCategory("nositelinks")
	end

	local other_lang = 'عنصر (' .. p.options.id .. ') في لغات أخرى'

	local suffix = ('&nbsp;[[d:%s|<sup class=reference title="%s">[%s]</sup>]]'):format(
		p.options.id .. "#sitelinks-wikipedia",
		other_lang,
		"لغات أخرى"
	)

	if isValid(targetLink) and isValid(targetSite) then
		local language = Frame:callParserFunction("#language", targetSite, "ar")
		suffix = ('[[:%s:%s|<sup class=reference title="%s (%s)">[%s]</sup>]]'):format(
			targetSite, targetLink, targetLink, p.options.id, language
		)
	end

	suffix = mw.text.tag("span", {
			class = "noprint",
			style = "font-size: smaller; font-style: normal; font-weight: normal;"
		},
		suffix
	)
	local catText = isValid(p.options.from_lua) and makeCategory("add") or ""

	return "&nbsp;" .. suffix .. catText
end

local function makeLink(title, suffix, sitelinksCount)
	local linkText = prepareText(title)
	local link
	local titleObj = mw.title.new(title)
	local cate = isValid(p.options.from_lua) and makeCategory("review") or ""

	if sitelinksCount == 0 and not isValid(p.options.wdlink) then
		link = linkText .. suffix
	elseif titleObj and titleObj.exists then
		link = linkText .. suffix .. cate
		mw.log('review "' .. title .. '", id: ' .. p.options.id)
	else
		title = mw.ustring.gsub(title, "^تصنيف:", "")
		linkText = mw.ustring.gsub(linkText, "^تصنيف:", "")
		link = ('[[%s|%s]]%s'):format(title, linkText, suffix)
	end

	debug("link: " .. link)
	return link
end

-- Main Functions
local function parseArgs(frame)
	p.options = getArgs(frame, {
		aliases = {
			wdlink = { "wdlink" },
			debug = { "debug" },
			en_label = { "enlabel" },
			use_en_target = { "en" },
			id = { "المعرف", "id", 2 },
			label = { "label", 1 },
			target = { "target", "لغ" },
			nocat = { "nocat" },
			noy = { "noy" },
			year = { "y" },
			text = { "text", "نص" },
			from_lua = { "fromlua", "from_lua" }
		}
	})
end

-- وظيفة مساعدة للحصول على النص الإنجليزي
local function get_en_label(target)
	if isValid(p.options.en_label) then
		return p.options.en_label
	elseif target == "en" then
		return labelIn("en")
	end

	return ""
end

function p.link(frame)
	parseArgs(frame)
	Frame = frame:getParent()
	local id = p.options.id

	if not isValid(id) then
		return "No ID"
	end

	-- الحصول على رابط الموقع المحلي
	local localSiteLink = mw.wikibase.sitelink(id)
	if localSiteLink then
		-- mw.log("remove: " .. id)
		return ('[[%s|%s]]%s%s'):format(
			localSiteLink, prepareText(localSiteLink), makeCategory("remove"), RTL
		)
	end

	-- تحديد الهدف الافتراضي (en) إذا تم طلب ذلك
	local target = p.options.use_en_target and "en" or p.options.target
	-- إعداد النصوص البديلة (en_label)
	local en_label = get_en_label(target)

	-- الحصول على عدد المواقع
	local sitelinksCount = countSiteLinks(id)

	local targetLink = isValid(target) and getSiteLink(target .. "wiki", id) or ""
	local suffix = makeSuffix(target, targetLink, sitelinksCount)

	-- إعداد التسمية العربية (ar_label)
	local ar_link = isValid(p.options.label) or isValid(labelIn("ar"))

	-- إذا كان هناك رابط عربي
	if isValid(ar_link) then
		debug("ar_link : " .. ar_link)
		return makeLink(ar_link, suffix, sitelinksCount) .. RTL
	end

	-- إذا كان هناك رابط هدف
	if isValid(targetLink) then
		debug("target " .. target .. ": " .. targetLink)
		return prepareText(targetLink) .. suffix .. RTL
	end

	-- إذا كان هناك نص إنجليزي (en_label)
	if isValid(en_label) then
		debug("en_label: " .. en_label)
		return prepareText(en_label) .. makeSuffix("", "", sitelinksCount) .. RTL
	end

	-- إذا لم يتم العثور على أي شيء
	debug("nothing found: en_label = " .. en_label)
	return ""
end

return p