-- Portal Pro :: UI/Tab_Leads.lua
-- The queue of people who just asked for a portal. This is the screen you actually live on.

local ADDON_NAME, PP = ...
local UI, T, U = PP.UI, PP.Theme, PP.U
local L = PP.L

local CARD_HEIGHT = 78

-- Zones where a portal is a rescue rather than a convenience. Hardcore players pay a
-- premium to get out of these, and the card highlights it so you can price accordingly.
local RESCUE_ZONES = {
	["stranglethorn vale"] = true,
	["the hinterlands"] = true,
	["badlands"] = true,
	["searing gorge"] = true,
	["burning steppes"] = true,
	["blasted lands"] = true,
	["tanaris"] = true,
	["felwood"] = true,
	["un'goro crater"] = true,
	["silithus"] = true,
	["winterspring"] = true,
	["eastern plaguelands"] = true,
	["western plaguelands"] = true,
	["azshara"] = true,
}

--- A chat message only tells us where the *sender* is if it came over a local channel.
--- Say and Yell are zone-scoped, so those genuinely mean "this player is standing in a
--- dangerous zone with me". Trade and General are city-wide or global and prove nothing,
--- so the badge deliberately doesn't appear for them rather than guessing.
local function isRescueLead(lead)
	if lead.channel ~= "SAY" and lead.channel ~= "YELL" then return false end
	local zone = (GetRealZoneText() or ""):lower()
	return RESCUE_ZONES[zone] or false
end

--------------------------------------------------------------------------------
-- Card
--------------------------------------------------------------------------------

local function createCard(parent)
	local card = UI:Panel(parent, "raised")
	UI:Border(card, "borderSubtle")

	-- Left accent stripe, coloured by lead priority
	card.stripe = card:CreateTexture(nil, "ARTWORK")
	card.stripe:SetWidth(2)
	card.stripe:SetPoint("TOPLEFT")
	card.stripe:SetPoint("BOTTOMLEFT")

	card.destIcon = card:CreateTexture(nil, "ARTWORK")
	card.destIcon:SetSize(30, 30)
	card.destIcon:SetPoint("TOPLEFT", T.space.md, -T.space.md)
	card.destIcon:SetTexCoord(0.08, 0.92, 0.08, 0.92)

	card.name = UI:Text(card, "", T.fontSize.md, "", "textPrimary")
	card.name:SetPoint("TOPLEFT", card.destIcon, "TOPRIGHT", T.space.sm, 0)

	card.badges = UI:Text(card, "", T.fontSize.xs, "", "warning")
	card.badges:SetPoint("LEFT", card.name, "RIGHT", T.space.sm, 0)

	card.dest = UI:Text(card, "", T.fontSize.sm, "", "accent")
	card.dest:SetPoint("TOPLEFT", card.name, "BOTTOMLEFT", 0, -2)

	card.message = UI:Text(card, "", T.fontSize.sm, "", "textSecondary")
	card.message:SetPoint("TOPLEFT", card.destIcon, "BOTTOMLEFT", 0, -T.space.sm)
	card.message:SetJustifyH("LEFT")
	-- Right edge is anchored to the action buttons further down, once they exist.

	card.meta = UI:Text(card, "", T.fontSize.xs, "", "textMuted", "RIGHT")
	card.meta:SetPoint("TOPRIGHT", -T.space.md, -T.space.md)

	-- Actions
	local function action(label, variant, width, handler, tooltip)
		local b = UI:Button(card, label, function()
			if card.lead then handler(card.lead) end
		end, variant, width, 22)
		if tooltip then UI:Tooltip(b, label, tooltip) end
		return b
	end

	card.whisperBtn = action(L["Whisper"], "secondary", 64, function(lead)
		PP.Leads:Whisper(lead, "greeting")
	end, { "Send your greeting template." })

	card.quoteBtn = action(L["Quote"], "secondary", 54, function(lead)
		PP.Leads:Whisper(lead, "quote")
	end, { "Send the price for this destination." })

	card.inviteBtn = action(L["Invite"], "primary", 58, function(lead)
		PP.Leads:Invite(lead)
	end, { "Invite to group and send the invite template." })

	card.dismissBtn = action("X", "ghost", 24, function(lead)
		PP.Leads:Remove(lead.id)
	end, { "Dismiss this lead." })

	card.blacklistBtn = action("!", "ghost", 24, function(lead)
		PP.Leads:Blacklist(lead)
	end, { "Never create a lead from this player again." })

	card.blacklistBtn:SetPoint("BOTTOMRIGHT", -T.space.md, T.space.sm)
	card.dismissBtn:SetPoint("RIGHT", card.blacklistBtn, "LEFT", -2, 0)
	card.inviteBtn:SetPoint("RIGHT", card.dismissBtn, "LEFT", -T.space.sm, 0)
	card.quoteBtn:SetPoint("RIGHT", card.inviteBtn, "LEFT", -4, 0)
	card.whisperBtn:SetPoint("RIGHT", card.quoteBtn, "LEFT", -4, 0)

	-- The message shares its row with the buttons, so clamp it to the leftmost button
	-- rather than the card edge. Anchoring to the button (not a fixed inset) means the
	-- text reclaims the space automatically when the window is widened.
	card.message:SetPoint("RIGHT", card.whisperBtn, "LEFT", -T.space.sm, 0)

	UI:Hoverable(card, "raised", "hover")
	return card
end

local function updateCard(card, lead, index)
	card.lead = lead
	if not lead then return end

	local classHex = U.ClassColorHex(lead.class)
	card.name:SetText(classHex .. lead.name .. "|r")

	-- Badges
	local badges = {}
	if lead.vip then badges[#badges + 1] = "|cff" .. T.hex.gold .. L["VIP"] .. "|r" end
	if lead.returning then badges[#badges + 1] = "|cff" .. T.hex.positive .. "REGULAR|r" end
	if isRescueLead(lead) then badges[#badges + 1] = "|cff" .. T.hex.warning .. L["Rescue"] .. "|r" end
	if lead.paid then badges[#badges + 1] = "|cff" .. T.hex.positive .. "PAID|r" end
	card.badges:SetText(table.concat(badges, "  "))

	-- Destination
	if lead.dest then
		card.destIcon:SetTexture(PP.Dest:Icon(lead.dest))
		card.destIcon:SetDesaturated(false)
		local price = PP.Dest:Price(lead.dest)
		card.dest:SetText(("%s · %s"):format(lead.dest.name, U.MoneyPlain(price)))
		card.dest:SetTextColor(T:C(PP.Dest:IsReachable(lead.dest) and "accent" or "negative"))
	else
		card.destIcon:SetTexture(134400)
		card.destIcon:SetDesaturated(true)
		card.dest:SetText(L["Unknown destination"])
		card.dest:SetTextColor(T:C("textMuted"))
	end

	card.message:SetText(U.Truncate(lead.message or "", 110))
	card.meta:SetText(("%s · %s"):format(lead.channelLabel or lead.channel or "", U.Ago(lead.ts)))

	-- Stripe + state
	local stripeColor = "borderSubtle"
	if lead.vip then stripeColor = "gold"
	elseif lead.status == "engaged" then stripeColor = "positive"
	elseif lead.dest then stripeColor = "accent" end
	card.stripe:SetColorTexture(T:C(stripeColor))

	card.whisperBtn:SetEnabledState(not lead.whispered)
	card.inviteBtn:SetEnabledState(not lead.invited)

	UI:Tooltip(card, lead.name, function()
		local lines = {
			"Full message:",
			lead.message or "",
			" ",
			("Matched with score %d"):format(lead.score or 0),
		}
		for _, reason in ipairs(lead.reasons or {}) do
			lines[#lines + 1] = "  " .. reason
		end
		local customer = PP.Ledger:GetCustomer(lead.name)
		if customer and customer.count > 0 then
			lines[#lines + 1] = " "
			lines[#lines + 1] = ("%d previous ports, %s total"):format(
				customer.count, U.MoneyPlain(customer.totalCopper))
		end
		return lines
	end)
end

--------------------------------------------------------------------------------
-- Tab
--------------------------------------------------------------------------------

local function build(parent)
	local frame = CreateFrame("Frame", nil, parent)

	-- Toolbar
	local bar = CreateFrame("Frame", nil, frame)
	bar:SetPoint("TOPLEFT", T.space.lg, -T.space.lg)
	bar:SetPoint("TOPRIGHT", -T.space.lg, -T.space.lg)
	bar:SetHeight(T.size.buttonHeight)

	local heading = UI:Text(bar, L["Leads"], T.fontSize.lg, "", "textPrimary")
	heading:SetPoint("LEFT")

	local subtitle = UI:Text(bar, "", T.fontSize.sm, "", "textMuted")
	subtitle:SetPoint("LEFT", heading, "RIGHT", T.space.sm, -1)
	frame.subtitle = subtitle

	local clear = UI:Button(bar, "Clear", function() PP.Leads:Clear() end, "ghost", 56, 24)
	clear:SetPoint("RIGHT")

	local detection = UI:Switch(bar, "Detection", PP.profile.detection.enabled, function(value)
		PP.profile.detection.enabled = value
	end)
	detection:SetPoint("RIGHT", clear, "LEFT", -T.space.md, 0)
	frame.detectionSwitch = detection

	UI:Tooltip(detection, "Chat detection", {
		"Whether Portal Pro reads chat looking for portal requests.",
		"With this off, no new leads appear.",
		" ",
		"This is the same setting as Settings -> Detection -> \"Scan chat for",
		"portal requests\", and the same as /pp on and /pp off. It's repeated",
		"here because it's the one you'll want to reach in a hurry.",
	})

	-- List
	local list = UI:ScrollList(frame, CARD_HEIGHT, createCard, updateCard, T.space.sm)
	list:SetPoint("TOPLEFT", bar, "BOTTOMLEFT", 0, -T.space.md)
	list:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -T.space.lg, T.space.lg)
	list:SetEmptyState(L["No leads yet"], L["Waiting for portal requests..."])
	frame.list = list

	return frame
end

local function refresh(frame)
	frame.list:SetData(PP.Leads.queue)
	frame.detectionSwitch:SetValue(PP.profile.detection.enabled, true)

	local n = PP.Leads:Count()
	frame.subtitle:SetText(n == 0 and "" or ("%d waiting"):format(n))
end

UI:RegisterTab({
	key = "leads",
	label = L["Leads"],
	icon = "Interface\\ICONS\\INV_Misc_GroupLooking",
	order = 1,
	build = build,
	refresh = refresh,
})
