-- ============================================================
-- VisitMe Addon - Final Build (No UI Version)
-- Case-Insensitive Commands + FIFO Vendors + Timer + Skip
-- Added: /kitohome + Extra Whisper on Connect + 1-Min Warning
-- RAID LEADER ONLY VERSION + #timeleft + Whisper Restriction
-- Updated: #vendors (single description per player)
-- ============================================================

local addonName = ...
print("|cff00ff00VisitMe loaded (No UI).|r")

---------------------------------------------------------------
-- GLOBAL STORAGE
---------------------------------------------------------------
Kito_Visits      = Kito_Visits      or {}
Kito_Vendors     = Kito_Vendors     or {}
KitoTime         = KitoTime         or 5
Kito_HomeMessage = Kito_HomeMessage or "No Current Player Tour!"

local whispered       = {}
local processing      = false
local currentTimer    = 0
local currentEntry    = nil
local previousMembers = {}
local warnedOneMinute = false

---------------------------------------------------------------
-- WHISPER QUEUE SYSTEM
---------------------------------------------------------------
local WhisperQueue = {}
local WhisperTickerRunning = false

local function ProcessWhisperQueue()
    if #WhisperQueue == 0 then
        WhisperTickerRunning = false
        return
    end

    local item = table.remove(WhisperQueue, 1)
    SendChatMessage(item.msg, "WHISPER", nil, item.target)
end

local function EnqueueWhisper(target, msg)

    -- DO NOT WHISPER unless player is raid leader
    if not IsInRaid() or not UnitIsGroupLeader("player") then
        return
    end

    table.insert(WhisperQueue, { target = target, msg = msg })

    if not WhisperTickerRunning then
        WhisperTickerRunning = true
        C_Timer.NewTicker(1, ProcessWhisperQueue)
    end
end

---------------------------------------------------------------
-- CONSTANTS
---------------------------------------------------------------
local VISIT_CMD     = "^#visitme%s*(.*)$"
local COMMANDS_CMD  = "^#commands$"
local HELP_CMD      = "^#help$"
local SKIP_CMD      = "^#skip$"
local VENDORS_CMD   = "^#vendors%s*(.*)$"

local CUSTOM_HELP_MESSAGE =
"Welcome! We are Free For All Visiting Each Others Houses/Vendors! Rclick Someones Portrait to Visit Them! To List Your House/Vendors Type #VisitMe/#Vendors and Add a Short Description! Type #Commands For a Full List of Commands! Or #Help To Get Started!"

local CUSTOM_COMMANDS_MESSAGE =
"Chat Commands: #visitme , #help , #skip , #commands , #timeleft , #vendors"

local JOIN_MESSAGE =
"Welcome! We are Free For All Visiting Each Others Houses/Vendors! Rclick Someones Portrait to Visit Them! To List Your House/Vendors Type #VisitMe/#Vendors and Add a Short Description! Type #Commands For a Full List of Commands! Or #Help To Get Started!"

---------------------------------------------------------------
-- UTILITY FUNCTIONS
---------------------------------------------------------------
local function FormatTime(seconds)
    local m = math.floor(seconds / 60)
    local s = seconds % 60
    return string.format("%dm %ds", m, s)
end

local function GetHouseEntryForSender(sender)
    sender = Ambiguate(sender, "none")

    if currentEntry and currentEntry.sender == sender then
        return "current", currentEntry
    end

    for i, entry in ipairs(Kito_Visits) do
        if entry.sender == sender then
            return i, entry
        end
    end

    return nil, nil
end

---------------------------------------------------------------
-- WHISPER NEW MEMBERS
---------------------------------------------------------------
local function WhisperNewMembers()

    -- DO NOT WHISPER unless raid leader
    if not IsInRaid() or not UnitIsGroupLeader("player") then
        return
    end

    local num    = GetNumGroupMembers()
    local isRaid = IsInRaid()

    for i = 1, num do
        local unit = isRaid and "raid"..i or "party"..i
        local name = UnitName(unit)

        if name and name ~= UnitName("player") then
            if not whispered[name] then

                EnqueueWhisper(name, JOIN_MESSAGE)

                if currentEntry then
                    local info = string.format(
                        "[VisitMe] Current tour: %s — \"%s\" — Time left: %dm %ds",
                        currentEntry.sender,
                        currentEntry.text,
                        math.floor(currentTimer / 60),
                        currentTimer % 60
                    )
                    EnqueueWhisper(name, info)
                else
                    EnqueueWhisper(name, "[VisitMe] " .. (Kito_HomeMessage or "No tour is active."))
                end

                whispered[name] = true
            end
        end
    end
end

---------------------------------------------------------------
-- HELP SYSTEM (#help)
---------------------------------------------------------------
local function HandleHelpCommand(msg, sender)
    if not msg:match(HELP_CMD) then return false end
    EnqueueWhisper(sender, CUSTOM_HELP_MESSAGE)
    return true
end

---------------------------------------------------------------
-- TIME LEFT SYSTEM (#timeleft)
---------------------------------------------------------------
local function HandleTimeLeft(msg, sender)
    if not msg:match("^#timeleft$") then return false end
    sender = Ambiguate(sender, "none")

    if currentEntry then
        local info = string.format(
            "[VisitMe] Current tour: %s — \"%s\" — Time left: %dm %ds",
            currentEntry.sender,
            currentEntry.text,
            math.floor(currentTimer / 60),
            currentTimer % 60
        )
        EnqueueWhisper(sender, info)
    else
        EnqueueWhisper(sender, "[VisitMe] No tour is currently active.")
    end

    local position = nil
    for i, entry in ipairs(Kito_Visits) do
        if entry.sender == sender then
            position = i
            break
        end
    end

    if position then
        local minutes = position * KitoTime
        local msg2 = string.format(
            "[VisitMe] Your house is #%d in queue. Estimated time until your tour: %d minutes.",
            position,
            minutes
        )
        EnqueueWhisper(sender, msg2)
    end

    return true
end

---------------------------------------------------------------
-- VISIT SYSTEM (#visitme)
---------------------------------------------------------------
local function HandleVisitMessage(msg, sender)
    local text = msg:match(VISIT_CMD)
    if text == nil then return false end

    if text == "" or text:match("^%s*$") then
        if not currentEntry then
            EnqueueWhisper(sender, "[VisitMe] " .. (Kito_HomeMessage or "No tour is active."))
            return true
        end

        local info = string.format(
            "[VisitMe] Current tour: %s — \"%s\" — Time left: %dm %ds",
            currentEntry.sender,
            currentEntry.text,
            math.floor(currentTimer / 60),
            currentTimer % 60
        )
        EnqueueWhisper(sender, info)
        return true
    end

    if currentEntry and currentEntry.sender == sender then
        currentEntry.text = text
        EnqueueWhisper(sender, "[VisitMe] Your active tour entry has been updated.")
        return true
    end

    for _, entry in ipairs(Kito_Visits) do
        if entry.sender == sender then
            entry.text = text
            EnqueueWhisper(sender, "[VisitMe] Your queued tour entry has been updated.")
            return true
        end
    end

    table.insert(Kito_Visits, {
        sender = sender,
        text   = text,
        time   = time(),
    })

    EnqueueWhisper(sender, "[VisitMe] Your tour entry has been added.")
    return true
end

---------------------------------------------------------------
-- COMMAND LIST (#commands)
---------------------------------------------------------------
local function HandleCommandsList(msg, sender)
    if not msg:match(COMMANDS_CMD) then return false end
    EnqueueWhisper(sender, CUSTOM_COMMANDS_MESSAGE)
    return true
end

---------------------------------------------------------------
-- SKIP SYSTEM (#skip)
---------------------------------------------------------------
local function HandleSkipCommand(msg, sender)
    if not msg:match(SKIP_CMD) then return false end

    if currentEntry and currentEntry.sender == sender then
        EnqueueWhisper(sender, "[VisitMe] You skipped your active tour.")
        currentEntry = nil
        currentTimer = 0
        processing   = false
        warnedOneMinute = false
        SendChatMessage("[VisitMe] Current tour has been skipped!", "RAID_WARNING")
        return true
    end

    for i = #Kito_Visits, 1, -1 do
        if Kito_Visits[i].sender == sender then
            table.remove(Kito_Visits, i)
            EnqueueWhisper(sender, "[VisitMe] Your queued tour entry has been removed.")
            return true
        end
    end

    if UnitIsGroupLeader("player") and currentEntry then
        SendChatMessage("[VisitMe] Raid leader skipped the current tour!", "RAID_WARNING")
        currentEntry = nil
        currentTimer = 0
        processing   = false
        warnedOneMinute = false
        return true
    end

    EnqueueWhisper(sender, "[VisitMe] You have no tour entry to skip.")
    return true
end

---------------------------------------------------------------
-- NEW VENDOR SYSTEM (#vendors)
---------------------------------------------------------------
local function HandleVendorsCommand(msg, sender)
    local text = msg:match(VENDORS_CMD)
    if text == nil then return false end

    sender = Ambiguate(sender, "none")

    -- No text → list all vendors
    if text == "" or text:match("^%s*$") then
        if #Kito_Vendors == 0 then
            EnqueueWhisper(sender, "[VisitMe] No vendor entries have been added.")
            return true
        end

        EnqueueWhisper(sender, "[VisitMe] Vendor List (oldest to newest):")

        for _, entry in ipairs(Kito_Vendors) do
            local line = string.format("%s — \"%s\"", entry.sender, entry.text)
            EnqueueWhisper(sender, line)
        end

        return true
    end

    -- Add/update single vendor entry
    local existingIndex = nil
    for i, entry in ipairs(Kito_Vendors) do
        if entry.sender == sender then
            existingIndex = i
            break
        end
    end

    if existingIndex then
        Kito_Vendors[existingIndex].text = text
        Kito_Vendors[existingIndex].time = time()
        EnqueueWhisper(sender, "[VisitMe] Your vendor description has been updated.")
        return true
    end

    table.insert(Kito_Vendors, {
        sender = sender,
        text   = text,
        time   = time(),
    })

    EnqueueWhisper(sender, "[VisitMe] Your vendor description has been added.")
    return true
end

---------------------------------------------------------------
-- REMOVE ENTRIES WHEN SOMEONE LEAVES
---------------------------------------------------------------
local function RemoveVisitsBySender(sender)
    if not sender then return end

    if currentEntry and currentEntry.sender == sender then
        currentEntry = nil
        currentTimer = 0
        processing   = false
        warnedOneMinute = false
        EnqueueWhisper(sender, "[VisitMe] Your tour entry was removed because you left the group.")
    end

    for i = #Kito_Visits, 1, -1 do
        if Kito_Visits[i].sender == sender then
            table.remove(Kito_Visits, i)
        end
    end

    for i = #Kito_Vendors, 1, -1 do
        if Kito_Vendors[i].sender == sender then
            table.remove(Kito_Vendors, i)
        end
    end
end

---------------------------------------------------------------
-- GROUP ROSTER TRACKING
---------------------------------------------------------------
local function ScanGroupMembers()
    local currentMembers = {}
    local num    = GetNumGroupMembers()
    local isRaid = IsInRaid()

    for i = 1, num do
        local unit = isRaid and "raid"..i or "party"..i
        local name = UnitName(unit)
        if name then currentMembers[name] = true end
    end

    for name in pairs(previousMembers) do
        if not currentMembers[name] then
            RemoveVisitsBySender(name)
        end
    end

    previousMembers = currentMembers
end

---------------------------------------------------------------
-- TIMER SYSTEM (with 1-min warning)
---------------------------------------------------------------
local ticker = C_Timer.NewTicker(1, function()

    if not currentEntry and #Kito_Visits == 0 then
        processing   = false
        currentTimer = 0
        warnedOneMinute = false
        return
    end

    if not currentEntry then
        currentEntry = table.remove(Kito_Visits, 1)
        currentTimer = KitoTime * 60
        processing   = true
        warnedOneMinute = false

        local announce = string.format(
            "[VisitMe] New Tour Started! Now visiting: %s — \"%s\" (%dm %ds remaining)",
            currentEntry.sender,
            currentEntry.text,
            math.floor(currentTimer / 60),
            currentTimer % 60
        )

        SendChatMessage(announce, "RAID_WARNING")
        return
    end

    currentTimer = currentTimer - 1

    if currentTimer == 60 and not warnedOneMinute then
        warnedOneMinute = true
        if #Kito_Visits > 0 then
            local nextEntry = Kito_Visits[1]
            local warnMsg = string.format(
                "[VisitMe] 1 minute left! Next tour: %s — \"%s\"",
                nextEntry.sender,
                nextEntry.text
            )
            SendChatMessage(warnMsg, "RAID_WARNING")
        end
    end

    if currentTimer <= 0 then
        SendChatMessage("[VisitMe] Time expired for: " .. currentEntry.text, "RAID_WARNING")
        currentEntry = nil
        currentTimer = 0
        processing   = false
        warnedOneMinute = false
    end
end)

---------------------------------------------------------------
-- CHAT EVENT HANDLER (RAID LEADER ONLY)
---------------------------------------------------------------
local chatFrame = CreateFrame("Frame")
chatFrame:RegisterEvent("CHAT_MSG_PARTY")
chatFrame:RegisterEvent("CHAT_MSG_PARTY_LEADER")
chatFrame:RegisterEvent("CHAT_MSG_RAID")
chatFrame:RegisterEvent("CHAT_MSG_RAID_LEADER")
chatFrame:RegisterEvent("CHAT_MSG_WHISPER")
chatFrame:RegisterEvent("CHAT_MSG_WHISPER_INFORM")

chatFrame:SetScript("OnEvent", function(self, event, msg, sender)
    msg = msg:lower()
    sender = Ambiguate(sender, "none")

    -- MUST be in a raid AND must be raid leader
    if not IsInRaid() or not UnitIsGroupLeader("player") then
        return
    end

    if HandleHelpCommand(msg, sender) then return end
    if HandleCommandsList(msg, sender) then return end
    if HandleTimeLeft(msg, sender) then return end
    if HandleSkipCommand(msg, sender) then return end
    if HandleVisitMessage(msg, sender) then return end
    if HandleVendorsCommand(msg, sender) then return end
end)

---------------------------------------------------------------
-- GROUP ROSTER EVENT HANDLER
---------------------------------------------------------------
local rosterFrame = CreateFrame("Frame")
rosterFrame:RegisterEvent("GROUP_ROSTER_UPDATE")

rosterFrame:SetScript("OnEvent", function()
    WhisperNewMembers()
    ScanGroupMembers()
end)

---------------------------------------------------------------
-- SLASH COMMANDS
---------------------------------------------------------------
SLASH_KITOTIME1 = "/kitotime"
SlashCmdList["KITOTIME"] = function(msg)
    local num = tonumber(msg)
    if not num then
        print("|cffff5555[VisitMe]|r Please enter a valid number.")
        return
    end
    KitoTime = num
    print("|cff00ff00[VisitMe]|r VisitMeTime set to: " .. KitoTime)
end

SLASH_KITOHOME1 = "/kitohome"
SlashCmdList["KITOHOME"] = function(msg)
    if msg and msg ~= "" then
        Kito_HomeMessage = msg
        print("|cff00ff00[VisitMe]|r Home message set to: " .. msg)
    else
        print("|cffff5555[VisitMe]|r Usage: /kitohome <message>")
    end
end