QuestComments = QuestComments or {}
NPCComments = NPCComments or {}
local QuestHelperFrame = CreateFrame("Frame", "QuestHelperFrame", UIParent, "BackdropTemplate")
QuestHelperFrame:SetSize(600, 400)
QuestHelperFrame:SetPoint("CENTER")
QuestHelperFrame:SetMovable(true)
QuestHelperFrame:EnableMouse(true)
QuestHelperFrame:RegisterForDrag("LeftButton")
QuestHelperFrame:SetScript("OnDragStart", QuestHelperFrame.StartMoving)
QuestHelperFrame:SetScript("OnDragStop", QuestHelperFrame.StopMovingOrSizing)
QuestHelperFrame:SetResizable(true)
QuestHelperFrame:SetResizeBounds(300, 150)

QuestHelperFrame:SetBackdrop({
    bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
    edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
    tile = true,
    tileSize = 32,
    edgeSize = 32,
    insets = { left = 11, right = 12, top = 12, bottom = 11 }
})

local function CreateResizeHandle(frame, point, sizeDirection)
    local handle = CreateFrame("Button", nil, frame)
    handle:SetSize(16, 16)
    handle:SetPoint(point, 5, 5)
    handle:SetNormalTexture("Interface\\CHATFRAME\\UI-ChatIM-SizeGrabber-Up")
    handle:SetHighlightTexture("Interface\\CHATFRAME\\UI-ChatIM-SizeGrabber-Highlight")
    handle:SetPushedTexture("Interface\\CHATFRAME\\UI-ChatIM-SizeGrabber-Down")

    handle:SetScript("OnMouseDown", function(self)
        frame:StartSizing(sizeDirection)
    end)

    handle:SetScript("OnMouseUp", function(self)
        frame:StopMovingOrSizing()
    end)

    return handle
end

local resizeHandleBL = CreateResizeHandle(QuestHelperFrame, "BOTTOMLEFT", "BOTTOMLEFT")
local resizeHandleBR = CreateResizeHandle(QuestHelperFrame, "BOTTOMRIGHT", "BOTTOMRIGHT")
local resizeHandleTL = CreateResizeHandle(QuestHelperFrame, "TOPLEFT", "TOPLEFT")
local resizeHandleTR = CreateResizeHandle(QuestHelperFrame, "TOPRIGHT", "TOPRIGHT")

local closeButton = CreateFrame("Button", nil, QuestHelperFrame, "UIPanelCloseButton")
closeButton:SetPoint("TOPRIGHT", -5, -5)

local clearButton = CreateFrame("Button", nil, QuestHelperFrame, "UIPanelButtonTemplate")
clearButton:SetSize(80, 22)
clearButton:SetPoint("TOPRIGHT", closeButton, "TOPLEFT", -25, -5)
clearButton:SetText("Clear")

local scrollFrame = CreateFrame("ScrollFrame", nil, QuestHelperFrame, "UIPanelScrollFrameTemplate")
scrollFrame:SetPoint("TOPLEFT", 20, -50)
scrollFrame:SetPoint("BOTTOMRIGHT", -40, 60)

local content = CreateFrame("Frame", nil, scrollFrame)
content:SetSize(scrollFrame:GetWidth() - 40, 1)
scrollFrame:SetScrollChild(content)

local checkboxes = {}

clearButton:SetScript("OnClick", function()
    for _, fontString in ipairs({content:GetRegions()}) do
        fontString:SetText("")
        fontString:Hide()
    end
    for _, child in ipairs({content:GetChildren()}) do
        child:Hide()
        child:SetParent(nil)
    end
    content:SetHeight(1)
end)

QuestHelperFrame:Hide()

local function ToggleQuestHelperFrame()
    if QuestHelperFrame:IsShown() then
        QuestHelperFrame:Hide()
    else
        QuestHelperFrame:Show()
    end
end

local function CreateMinimapButton()
    local minimapButton = CreateFrame("Button", "QuestHelperMinimapButton", Minimap)
    minimapButton:SetSize(32, 32)
    minimapButton:SetPoint("CENTER", Minimap, "CENTER", -75, 25)

    local icon = minimapButton:CreateTexture(nil, "BACKGROUND")
    icon:SetTexture("Interface\\AddOns\\RoachIQ_QuestHelperClassic\\RoachIQ_Icon.tga")
    icon:SetAllPoints(minimapButton)

    local mask = minimapButton:CreateMaskTexture(nil, "BACKGROUND")
    mask:SetTexture("Interface\\CHARACTERFRAME\\TempPortraitAlphaMask", "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE")
    mask:SetAllPoints(minimapButton)

    icon:AddMaskTexture(mask)

    local border = minimapButton:CreateTexture(nil, "OVERLAY")
    border:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder")
    border:SetSize(54, 54)
    border:SetPoint("TOPLEFT", minimapButton, "TOPLEFT")

    minimapButton:SetMovable(true)
    minimapButton:RegisterForDrag("LeftButton")

    local function onUpdate(self)
        local xpos, ypos = GetCursorPosition()
        local xmin, ymin = Minimap:GetLeft(), Minimap:GetBottom()

        xpos = xpos / UIParent:GetScale() - xmin - 70
        ypos = ypos / UIParent:GetScale() - ymin - 70

        local angle = math.deg(math.atan2(ypos, xpos))
        self:ClearAllPoints()
        self:SetPoint("CENTER", Minimap, "CENTER", cos(angle) * 80, sin(angle) * 80)
    end

    minimapButton:SetScript("OnDragStart", function(self)
        self:SetScript("OnUpdate", onUpdate)
    end)
    
    minimapButton:SetScript("OnDragStop", function(self)
        self:SetScript("OnUpdate", nil)
    end)

    minimapButton:SetScript("OnClick", function()
        ToggleQuestHelperFrame()
    end)

    minimapButton:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_LEFT")
        GameTooltip:AddLine("RoachIQ")
        GameTooltip:Show()
    end)

    minimapButton:SetScript("OnLeave", function(self)
        GameTooltip:Hide()
    end)
end

CreateMinimapButton()

local questDropdown = CreateFrame("Frame", "QuestHelperQuestDropdown", QuestHelperFrame, "UIDropDownMenuTemplate")
questDropdown:SetPoint("TOPLEFT", 10, -10)

local selectedQuestTitle = nil
local displayedComments = {}

local function trim(s)
    return s:match("^%s*(.-)%s*$")
end

local function splitMessage(message)
    local parts = {}
    local length = 10000000

    while #message > length do
        local pos = message:sub(1, length):match(".*()[%.!%?]") or length
        local part = trim(message:sub(1, pos))
        table.insert(parts, part)
        message = trim(message:sub(pos + 1))
    end
    local lastPart = trim(message)
    table.insert(parts, lastPart)
    return parts
end


local function parseMarkdown(text)
    local html = text

    -- Headers
    html = html:gsub("######%s*(.-)\n", "|cFF00FF00%1|r\n")
    html = html:gsub("#####%s*(.-)\n", "|cFF00FF00%1|r\n")
    html = html:gsub("####%s*(.-)\n", "|cFF00FF00%1|r\n")
    html = html:gsub("###%s*(.-)\n", "|cFF00FF00%1|r\n")
    html = html:gsub("##%s*(.-)\n", "|cFF00FF00%1|r\n")
    html = html:gsub("#%s*(.-)\n", "|cFF00FF00%1|r\n")

    -- Bold
    html = html:gsub("%*%*(.-)%*%*", "|cFFFFFF00%1|r")

    -- Italics
    html = html:gsub("%*(.-)%*", "|cFFFF0000%1|r")

    -- Bold and Italics
    html = html:gsub("%*%*%*(.-)%*%*%*", "|cFFFFFF00|cFFFF0000%1|r|r")

    -- Inline code
    html = html:gsub("`(.-)`", "|cFF00FF00%1|r")

    -- Links
    html = html:gsub("%[(.-)%]%((.-)%)", "|Hurl:%2|h%1|h")

    -- Unordered lists
    html = html:gsub("\n%- (.-)\n", "\n|cFFFFD700â€¢ %1|r\n")

    -- Ordered lists (capture the digits and represent properly)
    html = html:gsub("\n(%d+)%.%s*(.-)\n", "\n|cFFFFD700%1. %2|r\n")

    -- Blockquotes
    html = html:gsub("\n> (.-)\n", "\n|cFF888888%1|r\n")

    return html
end

local function GetNPCIDFromGUID(guid)
    if guid then
        local unitType, _, _, _, _, npcID = strsplit("-", guid)
        if unitType == "Creature" or unitType == "Vehicle" then
            return npcID
        end
    end
    return nil
end

local function ClearRoachIQIcon()
    local targetFrame = TargetFrame
    if targetFrame and targetFrame.RoachIQIcon then
        targetFrame.RoachIQIcon:Hide()
        targetFrame.RoachIQIcon = nil
    end
end

local function CreateRoachIQIcon(npcID)
    if not npcID then
        -- print("CreateRoachIQIcon: No NPC ID provided.")
        return
    end

    local targetFrame = TargetFrame
    if not targetFrame then
        -- print("CreateRoachIQIcon: No target frame found.")
        return
    end

    -- Clear any existing icon
    ClearRoachIQIcon()

    local icon = CreateFrame("Button", nil, targetFrame)
    icon:SetSize(32, 32)
    icon:SetPoint("RIGHT", targetFrame, "RIGHT", 30, 0) -- Adjust positioning here

    local iconTexture = icon:CreateTexture(nil, "BACKGROUND")
    iconTexture:SetTexture("Interface\\AddOns\\RoachIQ_QuestHelperClassic\\RoachIQ_Icon.tga")
    iconTexture:SetAllPoints(icon)

    local mask = icon:CreateMaskTexture(nil, "BACKGROUND")
    mask:SetTexture("Interface\\CHARACTERFRAME\\TempPortraitAlphaMask", "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE")
    mask:SetAllPoints(icon)
    iconTexture:AddMaskTexture(mask)

    local border = icon:CreateTexture(nil, "OVERLAY")
    border:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder")
    border:SetSize(54, 54)
    border:SetPoint("TOPLEFT", icon, "TOPLEFT")

    icon:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:AddLine("RoachIQ NPC Info")

        NPCComments = NPCComments or nil
        if NPCComments and NPCComments[npcID] then
            for _, comment in ipairs(NPCComments[npcID]) do
                GameTooltip:AddLine(parseMarkdown(comment.body), 1, 1, 1, true)
            end
        else
            GameTooltip:AddLine("No comments available.")
        end

        GameTooltip:Show()
    end)

    icon:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)

    targetFrame.RoachIQIcon = icon

    return icon
end

local function OnTargetChanged()
    local guid = UnitGUID("target")
    local npcID = GetNPCIDFromGUID(guid)

    if npcID and NPCComments and NPCComments[npcID] then
        CreateRoachIQIcon(npcID)
        -- print("OnTargetChanged: RoachIQIcon added for NPC ID:", npcID)
    else
        ClearRoachIQIcon()
        -- print("OnTargetChanged: No valid NPC ID found or no comments available.")
    end
end

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("PLAYER_TARGET_CHANGED")
eventFrame:SetScript("OnEvent", function(self, event, ...)
    if event == "PLAYER_TARGET_CHANGED" then
        OnTargetChanged()
    end
end)

local function addMessageToLog(content, comment, previousFrame, fallbackPreviousFrame)
    local parts = splitMessage(parseMarkdown(comment.body))
    local timestamp = comment.date or date("%Y-%m-%d %H:%M:%S")
    for _, part in ipairs(parts) do
        local messageFrame = CreateFrame("Frame", nil, content)
        messageFrame:SetSize(content:GetWidth() - 20, 1)

        local referenceFrame = previousFrame or fallbackPreviousFrame

        if referenceFrame then
            local referenceFrameHeight = referenceFrame:GetHeight() or 0
            messageFrame:SetPoint("TOPLEFT", referenceFrame, "BOTTOMLEFT", 0, -10)
        else
            messageFrame:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -10)
        end

        local timestampTextString = messageFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        timestampTextString:SetPoint("TOPLEFT", messageFrame, "TOPLEFT", 10, -10)
        timestampTextString:SetText(timestamp .. " - " .. comment.author)

        local messageTextString = messageFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        messageTextString:SetPoint("TOPLEFT", timestampTextString, "BOTTOMLEFT", 0, -5)
        messageTextString:SetWidth(messageFrame:GetWidth() - 20)
        messageTextString:SetJustifyH("LEFT")
        messageTextString:SetWordWrap(true)

        messageTextString:SetText(part)

        local textHeight = messageTextString:GetStringHeight()
        local frameHeight = timestampTextString:GetStringHeight() + textHeight + 20
        messageFrame:SetHeight(frameHeight)
        content:SetHeight(content:GetHeight() + frameHeight + 10)

        previousFrame = messageFrame

        table.insert(checkboxes, messageTextString)
    end

    return previousFrame
end

local function GetQuestIDByTitle(questTitle)
    for i = 1, GetNumQuestLogEntries() do
        local title, _, _, isHeader, _, _, _, questID = GetQuestLogTitle(i)
        if not isHeader and title == questTitle then
            return tostring(questID)  -- Convert questID to string before returning
        end
    end
    return nil
end

local function GetQuestZoneByTitle(questTitle)
    for i = 1, GetNumQuestLogEntries() do
        local title, _, _, isHeader, _, _, _, questID, _, _, _, _, _, _, _, zone = GetQuestLogTitle(i)
        if not isHeader and title == questTitle then
            return zone
        end
    end
    return nil
end

local function GetQuestLevelByTitle(questTitle)
    for i = 1, GetNumQuestLogEntries() do
        local title, level, _, isHeader, _, _, _, questID = GetQuestLogTitle(i)
        if not isHeader and title == questTitle then
            return level
        end
    end
    return nil
end


local function addUserCommentUI(comment)
    local commentKey = comment.author .. "-" .. comment.body
    local timestamp = date("%Y-%m-%d %H:%M:%S")
    if not displayedComments[commentKey] then
        addMessageToLog(content, comment, nil, lastLoadedCommentFrame)
        displayedComments[commentKey] = true
    end
end

local function loadComments()
    -- Clear previous comments
    for _, fontString in ipairs({content:GetRegions()}) do
        fontString:SetText("")
        fontString:Hide()
    end
    for _, child in ipairs({content:GetChildren()}) do
        child:Hide()
        child:SetParent(nil)
    end
    content:SetHeight(1)  -- Reset content height

    displayedComments = {}
    local comments = {}
    local seenComments = {}
    local questID = GetQuestIDByTitle(selectedQuestTitle)

    if questID and QuestComments then
        for _, comment in pairs(QuestComments[questID] or {}) do
            if not seenComments[comment.author .. "-" .. comment.body] then
                table.insert(comments, comment)
                seenComments[comment.author .. "-" .. comment.body] = true
            end
        end
    end

    if RoachIQ_QuestHelperClassicSavedVariables and RoachIQ_QuestHelperClassicSavedVariables.userComments then
        for _, comment in ipairs(RoachIQ_QuestHelperClassicSavedVariables.userComments) do
            if comment.quest_id == questID and not seenComments[comment.author .. "-" .. comment.body] then
                table.insert(comments, comment)
                seenComments[comment.author .. "-" .. comment.body] = true
            end
        end
    end

    local previousFrame = nil  -- Variable to track the previous frame for correct alignment

    local function displayComments(index)
        if index > #comments then
            return
        end

        local comment = comments[index]
        previousFrame = addMessageToLog(content, comment, previousFrame)

        C_Timer.After(0.01, function() displayComments(index + 1) end)
    end

    -- Start displaying comments
    if #comments > 0 then
        displayComments(1)
        lastLoadedCommentFrame = previousFrame  -- Update lastLoadedCommentFrame
    end
end


local function handleUserCommentMessage(message, sender)
    local questTitle, commentText = message:match("!roachcomment (.-) %- (.+)")
    if questTitle and commentText then
        local questID = GetQuestIDByTitle(questTitle) or "0"
        local questZone = GetQuestZoneByTitle(questTitle) or "Unknown Zone"
        local questLevel = GetQuestLevelByTitle(questTitle) or 1
        local senderParts = { strsplit("-", sender) }
        local fullSender = senderParts[1] .. "-" .. GetRealmName()

        local timestamp = date("%Y-%m-%d %H:%M:%S")

        local existingComment = QuestComments[questID] and QuestComments[questID][fullSender]

        if existingComment then
            existingComment.body = commentText
            existingComment.quest_title = questTitle
            existingComment.quest_zone = questZone
            existingComment.quest_level = questLevel
            existingComment.timestamp = timestamp
        else
            local commentID = math.random(1000000, 9999999)
            local newComment = {
                quest_id = questID,
                comment_id = commentID,
                author = fullSender,
                body = commentText,
                quest_title = questTitle,
                quest_zone = questZone,
                quest_level = questLevel,
                timestamp = timestamp
            }
            QuestComments[questID] = QuestComments[questID] or {}
            QuestComments[questID][fullSender] = newComment
            addUserCommentUI(newComment)
        end
    end
end

local function initializeSavedVariables()
    if not RoachIQ_QuestHelperClassicSavedVariables then
        RoachIQ_QuestHelperClassicSavedVariables = { userComments = {}, muteWhispers = true }
    end
    if not RoachIQ_QuestHelperClassicSavedVariables.userComments then
        RoachIQ_QuestHelperClassicSavedVariables.userComments = {}
    end
    if not RoachIQ_QuestHelperClassicSavedVariables.muteWhispers then
        RoachIQ_QuestHelperClassicSavedVariables.muteWhispers = true
    end
end

local function InitializeQuestDropdown(self, dropdownLevel)
    local info = UIDropDownMenu_CreateInfo()
    for i = 1, GetNumQuestLogEntries() do
        local title, _, _, isHeader, _, _, _, questID = GetQuestLogTitle(i)
        if not isHeader and questID then
            info.text = title
            info.func = function()
                selectedQuestTitle = title
                UIDropDownMenu_SetText(questDropdown, title)
                loadComments() -- Reload comments when a quest is selected
            end
            UIDropDownMenu_AddButton(info, dropdownLevel)
        end
    end
end

UIDropDownMenu_Initialize(questDropdown, InitializeQuestDropdown)
UIDropDownMenu_SetWidth(questDropdown, 150)
UIDropDownMenu_SetButtonWidth(questDropdown, 124)
UIDropDownMenu_SetText(questDropdown, "Select Quest")
UIDropDownMenu_JustifyText(questDropdown, "LEFT")

local function OnChannelMessageEvent(self, event, ...)
    local args = {...}
    if event == "CHAT_MSG_CHANNEL" then
        local channelName = "RoachIQ"
        local channelNumber = GetChannelName(channelName)
        for _, v in ipairs(args) do
            if v == channelNumber then
                local message = args[1]
                local sender = args[2]
                if sender == UnitName("player") then return end
                if message:sub(1, 13) == "!roachcomment" then
                    handleUserCommentMessage(message, sender)
                end
                break
            end
        end
    elseif event == "PLAYER_REGEN_DISABLED" then
        inCombat = true
    elseif event == "PLAYER_REGEN_ENABLED" then
        inCombat = false
    end
end

local addonFrame = CreateFrame("Frame")
addonFrame:RegisterEvent("ADDON_LOADED")
addonFrame:RegisterEvent("CHAT_MSG_CHANNEL")
addonFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
addonFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
addonFrame:RegisterEvent("PLAYER_LOGOUT")
addonFrame:SetScript("OnEvent", function(self, event, ...)
    if event == "ADDON_LOADED" then
        local addonName = ...
        if addonName == "RoachIQ_QuestHelperClassic" then
            if not QuestHelperFrame.text then
                QuestHelperFrame.text = QuestHelperFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
                QuestHelperFrame.text:SetPoint("TOPLEFT", 10, -10)
                QuestHelperFrame.text:SetPoint("BOTTOMRIGHT", -10, 10)
                QuestHelperFrame.text:SetJustifyH("LEFT")
                QuestHelperFrame.text:SetJustifyV("TOP")
                QuestHelperFrame.text:SetShadowColor(0, 0, 0, 1)
                QuestHelperFrame.text:SetShadowOffset(1, -1)
            end
            initializeSavedVariables()
            loadComments()
            self:UnregisterEvent("ADDON_LOADED")
        end
    else
        OnChannelMessageEvent(self, event, ...)
    end
end)

local commentFrame = CreateFrame("Frame", nil, QuestHelperFrame, "BackdropTemplate")
commentFrame:SetSize(550, 50)
commentFrame:SetPoint("BOTTOMLEFT", 10, 10)
commentFrame:SetBackdrop({
    bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
    edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
    tile = true,
    tileSize = 32,
    edgeSize = 32,
    insets = { left = 11, right = 12, top = 12, bottom = 11 }
})
commentFrame:SetBackdropColor(0, 0, 0, 0.8)

local commentInputBox = CreateFrame("EditBox", nil, commentFrame, "InputBoxTemplate")
commentInputBox:SetPoint("LEFT", 19, 0)
commentInputBox:SetSize(420, 30)
commentInputBox:SetAutoFocus(false)
commentInputBox:SetTextInsets(10, 10, 5, 5)
commentInputBox:SetFontObject("GameFontHighlight")
commentInputBox:SetMultiLine(false)
commentInputBox:SetMaxLetters(255)
commentInputBox:EnableMouse(true)
commentInputBox:SetScript("OnEscapePressed", commentInputBox.ClearFocus)

local submitButton = CreateFrame("Button", nil, commentFrame, "UIPanelButtonTemplate")
submitButton:SetSize(80, 22)
submitButton:SetPoint("RIGHT", -10, 0)
submitButton:SetText("Submit")

local function resizeCommentFrame()
    local frameWidth = QuestHelperFrame:GetWidth() - 40
    commentFrame:SetWidth(frameWidth)
    commentInputBox:SetWidth(frameWidth - submitButton:GetWidth() - 30)
end

QuestHelperFrame:SetScript("OnSizeChanged", function()
    resizeCommentFrame()
    content:SetWidth(scrollFrame:GetWidth() - 40)
end)

resizeCommentFrame()

local function submitComment()
    local commentText = commentInputBox:GetText()
    if commentText ~= "" then
        if selectedQuestTitle and selectedQuestTitle ~= "Select Quest" then
            local channelName = "RoachIQ"
            local channel = GetChannelName(channelName)
            local user = UnitName("player")
            local fullMessage = "!roachcomment " .. selectedQuestTitle .. " - " .. commentText

            if channel > 0 then
                SendChatMessage(fullMessage, "CHANNEL", nil, channel)
            else
                handleUserCommentMessage(fullMessage, user)
            end

            commentInputBox:SetText("")
            handleUserCommentMessage(fullMessage, user)
        end
    end
end

commentInputBox:SetScript("OnEnterPressed", function()
    submitComment()
end)

submitButton:SetScript("OnClick", function()
    commentInputBox:ClearFocus()
    submitComment()
end)
