---@diagnostic disable: undefined-field, undefined-global
---@type string
local AddonName = ...
---@class Private
local Private = select(2, ...)
local wt = Private.Ace
---@class WTAPI
local WTAPI = WTAPI

local AceGUI = LibStub("AceGUI-3.0")

local frame = nil
local framePoint = "CENTER"
local frameRelativePoint = "CENTER"
local frameX = 0
local frameY = 0

function wt:Assignment()
    if frame then return end

    local colWidth = 300
    local fullWidth = colWidth * 2 + 20

    frame = AceGUI:Create("Frame")
    frame:SetWidth(fullWidth + 20)
    -- frame:SetHeight(350)
    frame:EnableResize(false)
    frame:SetTitle("Wild Things")
    frame:SetStatusText("Assignments")
    frame:SetLayout("Flow")
    frame:SetCallback("OnClose", function(widget)
        wt:ReleaseAssignmentFrame()
    end)
    frame:SetPoint(framePoint, UIParent, frameRelativePoint, frameX, frameY)

    -- Keyboard handling: intercept ESC while allowing other keys
    frame.frame:EnableKeyboard(true)
    frame.frame:SetPropagateKeyboardInput(true)
    frame.frame:SetScript("OnKeyDown", function(self, key)
        if key == "ESCAPE" then
            self:SetPropagateKeyboardInput(false)
            wt:ReleaseAssignmentFrame()
        end
    end)
    frame.frame:SetScript("OnKeyUp", function(self)
        self:SetPropagateKeyboardInput(true)
    end)

    if (Private.encounterIdToName[wt.db.profile.assignment.current_encounter_id]) then
        local creatureID, bossName, bossDescription, displayInfo, iconImage, uiModelSceneID =
            EJ_GetCreatureInfo(1, Private.encounterIdToJournalId[wt.db.profile.assignment.current_encounter_id])

        local label = AceGUI:Create("Label")
        if iconImage and iconImage ~= "" then
            label:SetText(bossName)
            label:SetImage(iconImage)
        else
            -- Fallback if no icon is returned
            label:SetText(Private.encounterIdToName[wt.db.profile.assignment.current_encounter_id])
            label:SetImage(("Interface\\AddOns\\%s\\Media\\Icons\\icon.tga"):format(AddonName))
        end
        label:SetWidth(colWidth*1.5)
        label:SetFontObject(GameFontNormalHuge)
        label:SetImageSize(60, 30)
        frame:AddChild(label)
    end

    local btn = AceGUI:Create("Button")
    btn:SetWidth(colWidth/2)
    btn:SetCallback("OnClick", function()
        wt:ReleaseAssignmentFrame()
        wt:Assignment()
        print("|cff99ff00Wild Things:|r ", "Assignments refreshed.")
    end)
    btn:SetText("Refresh")
    frame:AddChild(btn)

    local function addHeading(text)
        local heading = AceGUI:Create("Heading")
        heading:SetFullWidth(true)
        heading:SetText(text)
        frame:AddChild(heading)
    end

    addHeading("Your Assignments")

    local assignmentCount = 0
    local notes = _G.VMRT.Note.Text1 or _G.VExRT.Note.Text1
    if notes then

        local assignmentId = nil
        local linePos = nil
        local interruptNpcId = nil
        local interruptSpellId = nil
        local interruptMark = nil

        for line in notes:gmatch("[^\r\n]+") do
            if not string.find(line, "^{time:") then
                if type(linePos) == "number" then
                    linePos = linePos + 1
                end
                if string.find(line, "start") then
                    linePos = 0
                    assignmentId = line:match("(.+)start")
                end
                if string.find(line, "end") then
                    assignmentId = nil
                    linePos = nil
                    interruptNpcId = nil
                    interruptSpellId = nil
                    interruptMark = nil
                end
                if assignmentId == "int" and string.find(line, "npc:") then
                    interruptNpcId = line:match("npc:(.+)")
                end
                if assignmentId == "int" and string.find(line, "spell:") then
                    interruptSpellId = line:match("spell:(.+)")
                end
                if assignmentId == "int" and interruptNpcId and interruptSpellId and string.find(line, "^%{") then
                    interruptMark = line:match("^%{(.+)%}")
                end
                if string.find(line, "^§WT") then
                    assignmentId = line:match("§WT%s(.+)%s%-%s")
                    line = line:match("^§WT%s.-%s%-%s(.+)")
                end

                local playerFound = line:match(Private.playerName)

                if playerFound and assignmentId and ( (Private.assignmentIds[assignmentId] or
                    (linePos and Private.assignmentIds[assignmentId .. linePos]) ) or
                    (interruptNpcId and interruptSpellId and interruptMark and Private.assignmentIds[assignmentId .. ":" .. interruptNpcId .. ":" .. interruptSpellId .. ":" .. interruptMark]) ) then

                    local id = assignmentId

                    if linePos and not interruptNpcId then
                        id = id .. linePos
                        id = linePos and id:gsub(".+%d", Private.assignmentIds)
                    elseif interruptNpcId and interruptSpellId then
                        id = id .. ":" .. interruptNpcId .. ":" .. interruptSpellId .. ":" .. interruptMark
                        id = linePos and id:gsub(".+", Private.assignmentIds)
                    else
                        id = id:gsub(".+", Private.assignmentIds)
                    end

                    if id then
                        local playerPos = 1

                        local i = 1
                        for player in line:gmatch("(.-)%s") do
                            player = player:match("||c%x%x%x%x%x%x%x%x(.-)||r") or player -- Remove name coloring (if any)
                            if player == Private.playerName then
                                playerPos = i
                            end
                            i = i + 1
                        end

                        id = id:gsub("{pos}", playerPos)

                        if string.find(id, "{pos%+.+}") then
                            local number_to_add = id:match("{pos%+(.+)}")
                            id = id:gsub("{pos%+.+}", playerPos+number_to_add)
                        end

                        if string.find(id, "{pos1%:.+}") then
                            if playerPos == 1 then
                                local pos1_text = id:match("{pos1%:(.+)}")
                                id = id:gsub("{pos1%:.+}", pos1_text)
                            else
                                id = id:gsub("{pos1%:.+}", "")
                            end
                        end

                        wt:AssignmentLine(id, playerPos, linePos, colWidth, fullWidth)

                        assignmentCount = assignmentCount + 1
                    end
                end


            end
        end

    end

    local imageHeight = 0
    local currentEncounterId = wt.db.profile.assignment.current_encounter_id
    if Private.assignmentImages[currentEncounterId] then
        for _, imageData in ipairs(Private.assignmentImages[currentEncounterId]) do
            local icon = AceGUI:Create("Icon")
            icon:SetImage((imageData.path):format(AddonName))  -- set image
            icon:SetImageSize(imageData.width, imageData.height)  -- set image size
            icon:SetWidth(imageData.width)  -- set frame width
            icon.frame:EnableMouse(false)  -- disable mouse interaction
            frame:AddChild(icon)  -- add icon to frame
            imageHeight = imageData.height
        end
    end

    frame:SetHeight(220 + imageHeight + assignmentCount * 25)

    addHeading("Options")
    local checkbox = AceGUI:Create("CheckBox")
    checkbox:SetType("checkbox")
    checkbox:SetFullWidth(true)
    checkbox:SetLabel("Auto open")
    checkbox:SetDescription("Automatically open the Assignment window when a new Assignment is available.")
    checkbox:SetValue(wt.db.profile.assignment.auto_open)
    checkbox:SetCallback("OnValueChanged", function(widget, event, value)
        wt.db.profile.assignment.auto_open = value
    end)
    frame:AddChild(checkbox)
end

function wt:ReleaseAssignmentFrame()
    if not frame then return end

    local point, _, relativePoint, x, y = frame:GetPoint(1)
    framePoint = point
    frameRelativePoint = relativePoint
    frameX = x
    frameY = y

    frame:ReleaseChildren()
    AceGUI:Release(frame)
    frame = nil
end

function wt:IsAssignmentFrameOpen()
    if frame then
        return true
    end
    return false
end

function wt:AssignmentLine(id, pos, linePos, colWidth, fullWidth)
    if not frame then return end

    local grp = AceGUI:Create("SimpleGroup")
    grp:SetLayout("Flow")
    grp:SetWidth(fullWidth)
    grp:SetHeight(100)
    frame:AddChild(grp)

    local txt = AceGUI:Create("Label")
    txt:SetText(id)
    txt:SetWidth(colWidth*2.0)
    txt:SetFontObject(GameFontNormalLarge)
    grp:AddChild(txt)
end
