-- Portal Pro :: Modules/MailWatch.lua
-- Payments and refunds that arrive by post. Common when a customer disconnects mid-service
-- or when you refund someone who has already logged off.

local ADDON_NAME, PP = ...
local U, C = PP.U, PP.C

local MailW = PP:NewModule("MailWatch")
PP.MailWatch = MailW

local hooked = false

local function onIncoming(delta, partner)
	if delta <= 0 then return end
	partner = partner or "Unknown"

	local customer = PP.Ledger:GetCustomer(partner)
	local lead = PP.Leads:FindByName(partner)
	local destKey = lead and lead.destKey or nil

	PP.Ledger:RecordPayment(partner, delta, destKey, "mail", "Received by mail")
	PP:Print(("Received %s by mail from %s"):format(U.Money(delta), partner))
	PP:Fire("PAYMENT_RECEIVED", partner, delta, destKey)
end

local function onOutgoing(delta, recipient)
	if delta >= 0 then return end
	local amount = -delta
	recipient = recipient or "Unknown"

	local customer = PP.Ledger:GetCustomer(recipient)
	if customer and (customer.count or 0) > 0 then
		local linked
		for _, e in ipairs(PP.Ledger:Query({ customer = recipient, kind = "payment" })) do
			if PP.Ledger:RefundedAmount(e.id) < e.copper then linked = e.id end
		end
		PP.Ledger:RecordRefund(recipient, amount, linked, "mail", "Refunded by mail")
		PP:Print(("Refunded %s to %s by mail"):format(U.Money(amount), recipient))
		PP:Fire("REFUND_ISSUED", recipient, amount)
	else
		PP:Debug("mailed gold to non-customer, not booked:", recipient)
	end
end

function MailW:OnEnable()
	if hooked then return end
	hooked = true

	-- Taking money off a mail: capture the sender before the money moves.
	if _G.TakeInboxMoney then
		hooksecurefunc("TakeInboxMoney", function(index)
			local _, _, sender, _, money = GetInboxHeaderInfo(index)
			if not money or money <= 0 then return end
			PP.MoneyWatch:Expect("mail", C.ShortName(sender), 8, onIncoming)
		end)
	end

	-- Sending money: covers refunds issued by post.
	if _G.SendMail then
		hooksecurefunc("SendMail", function(recipient)
			local money = GetSendMailMoney and GetSendMailMoney() or 0
			if not money or money <= 0 then return end
			PP.MoneyWatch:Expect("mail", C.ShortName(recipient), 8, onOutgoing)
		end)
	end

	-- "Take All" style bulk collection also routes through TakeInboxMoney on this client,
	-- so no extra handling is needed. COD payments are outgoing and land in onOutgoing.
end
