local _, ns = ...
local L = ns.L or {}

local DATA = ns.Data or {}
local MIDNIGHT_LOST_LEGENDS_QUEST_ID = DATA.MIDNIGHT_LOST_LEGENDS_QUEST_ID or 89268
local MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID = DATA.MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID or 92713
local MIDNIGHT_LOST_LEGENDS_REPEATABLE_POOL = DATA.MIDNIGHT_LOST_LEGENDS_REPEATABLE_POOL or {}
local MIDNIGHT_LOST_LEGENDS_META_QUEST_ID = DATA.MIDNIGHT_LOST_LEGENDS_META_QUEST_ID or 93891

local Quest = ns.Quest or {}
local isQuestCompleted = Quest.IsQuestCompleted
local isQuestActive = Quest.IsQuestActive
local getTaskQuestIDsOnMap = Quest.GetTaskQuestIDsOnMap
local parseObjectiveFraction = Quest.ParseObjectiveFraction
local getQuestObjectiveLines = Quest.GetQuestObjectiveLines
local isQuestTurnInReady = Quest.IsQuestTurnInReady
local getQuestObjectiveProgressText = Quest.GetQuestObjectiveProgressText
local getQuestTitle = Quest.GetQuestTitle

local LostLegends = {}
ns.WorldWeeklyLostLegends = LostLegends

local function getActiveQuestStatusText(questID, readyToTurnIn, turnInText, openFallback)
    if readyToTurnIn then
        return turnInText or (L.STATUS_TURNIN or "Turn in")
    end

    if type(getQuestObjectiveProgressText) == "function" then
        local progressText = getQuestObjectiveProgressText(questID)
        if type(progressText) == "string" and progressText ~= "" then
            return progressText
        end
    end

    return openFallback or (L.STATUS_OPEN or "Accepted")
end

local function isTaskQuestVisibleOnAnyMap(questID, mapIDs)
    if not questID or questID <= 0 then
        return false, nil
    end

    for _, mapID in ipairs(mapIDs or {}) do
        for _, visibleQuestID in ipairs(getTaskQuestIDsOnMap(mapID)) do
            if visibleQuestID == questID then
                return true, mapID
            end
        end
    end

    return false, nil
end

local function isStrictLostLegendsTurnInReady(questID)
    if not questID or questID <= 0 or not isQuestActive(questID) or isQuestCompleted(questID) then
        return false
    end

    if C_QuestLog and type(C_QuestLog.ReadyForTurnIn) == "function" then
        local okReady, readyForTurnIn = pcall(C_QuestLog.ReadyForTurnIn, questID)
        if okReady and readyForTurnIn then
            return true
        end
    end

    local sawObjective = false
    if C_QuestLog and type(C_QuestLog.GetQuestObjectives) == "function" then
        local okObjectives, objectives = pcall(C_QuestLog.GetQuestObjectives, questID)
        if okObjectives and type(objectives) == "table" and #objectives > 0 then
            for _, objective in ipairs(objectives) do
                local text = type(objective) == "table" and (objective.text or objective.description) or nil
                local current, maximum = parseObjectiveFraction(text)
                local finished = type(objective) == "table"
                    and (objective.finished == true or objective.isFinished == true or objective.completed == true)
                    or false

                if finished then
                    sawObjective = true
                elseif current and maximum then
                    sawObjective = true
                    if current < maximum then
                        return false
                    end
                else
                    return false
                end
            end

            return sawObjective
        end
    end

    local parsedAny = false
    for _, objectiveText in ipairs(getQuestObjectiveLines(questID)) do
        local current, maximum = parseObjectiveFraction(objectiveText)
        if current and maximum then
            parsedAny = true
            if current < maximum then
                return false
            end
        else
            return false
        end
    end

    return parsedAny
end

function LostLegends.BuildRow()
    local label = L.PVE_EVENTS_ROW_LOST_LEGENDS or "Lost Legends"
    local activeQuestID = nil
    local completedQuestID = nil

    for _, questID in ipairs(MIDNIGHT_LOST_LEGENDS_REPEATABLE_POOL) do
        if isQuestCompleted(questID) then
            completedQuestID = questID
            break
        end
        if not activeQuestID and isQuestActive(questID) then
            activeQuestID = questID
        end
    end

    if completedQuestID then
        local title = getQuestTitle(completedQuestID, label)
        return {
            key = "lost_legends",
            label = label,
            text = L.STATUS_DONE or "Done",
            status = "complete",
            seen = true,
            completed = true,
            questID = completedQuestID,
            tooltipTitle = (title and title ~= "") and string.format("%s - %s", label, title) or label,
            tooltipLines = {
                L.PVE_EVENTS_DONE_HINT or "Already completed this week.",
            },
        }
    end

    if activeQuestID then
        local readyToTurnIn = isStrictLostLegendsTurnInReady(activeQuestID)
        local title = getQuestTitle(activeQuestID, label)
        local tooltipLines = getQuestObjectiveLines(activeQuestID)
        if #tooltipLines == 0 then
            tooltipLines[1] = readyToTurnIn
                and (L.PVP_WEEKLY_TURNIN_TOOLTIP or "This quest is done and can now be turned in.")
                or (L.PVE_EVENTS_ACTIVE_HINT or "This quest is active. Check the quest log for the current objective.")
        end

        return {
            key = "lost_legends",
            label = label,
            text = getActiveQuestStatusText(activeQuestID, readyToTurnIn),
            status = readyToTurnIn and "turnin" or "open",
            seen = true,
            completed = false,
            questID = activeQuestID,
            turnInQuestID = readyToTurnIn and activeQuestID or nil,
            tooltipTitle = (title and title ~= "") and string.format("%s - %s", label, title) or label,
            tooltipLines = tooltipLines,
        }
    end

    if isQuestActive(MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID) then
        local readyToTurnIn = isQuestTurnInReady(MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID)
        local title = getQuestTitle(MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID, label)
        local tooltipLines = getQuestObjectiveLines(MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID)
        if #tooltipLines == 0 then
            tooltipLines[1] = readyToTurnIn
                and (L.PVE_EVENTS_LOST_LEGENDS_RELIC_HINT or "Turn this quest in and choose a relic to start this week's Lost Legends quest.")
                or (L.PVE_EVENTS_ACTIVE_HINT or "This quest is active. Check the quest log for the current objective.")
        elseif readyToTurnIn then
            tooltipLines[#tooltipLines + 1] = L.PVE_EVENTS_LOST_LEGENDS_RELIC_HINT
                or "Turn this quest in and choose a relic to start this week's Lost Legends quest."
        end

        return {
            key = "lost_legends",
            label = label,
            text = getActiveQuestStatusText(
                MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID,
                readyToTurnIn,
                L.PVE_EVENTS_LOST_LEGENDS_CHOOSE or "Choose"
            ),
            status = readyToTurnIn and "turnin" or "open",
            seen = true,
            completed = false,
            questID = MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID,
            turnInQuestID = readyToTurnIn and MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID or nil,
            tooltipTitle = (title and title ~= "") and string.format("%s - %s", label, title) or label,
            tooltipLines = tooltipLines,
        }
    end

    if isQuestCompleted(MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID) then
        local title = getQuestTitle(MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID, label)
        return {
            key = "lost_legends",
            label = label,
            text = L.PVE_EVENTS_LOST_LEGENDS_CHOOSE or "Choose",
            status = "turnin",
            seen = true,
            completed = false,
            questID = MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID,
            turnInQuestID = MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID,
            tooltipTitle = (title and title ~= "") and string.format("%s - %s", label, title) or label,
            tooltipLines = {
                L.PVE_EVENTS_LOST_LEGENDS_RELIC_HINT or "Turn this quest in and choose a relic to start this week's Lost Legends quest.",
            },
        }
    end

    if isQuestActive(MIDNIGHT_LOST_LEGENDS_QUEST_ID) then
        local readyToTurnIn = isQuestTurnInReady(MIDNIGHT_LOST_LEGENDS_QUEST_ID)
        local title = getQuestTitle(MIDNIGHT_LOST_LEGENDS_QUEST_ID, label)
        local tooltipLines = getQuestObjectiveLines(MIDNIGHT_LOST_LEGENDS_QUEST_ID)
        if #tooltipLines == 0 then
            tooltipLines[1] = readyToTurnIn
                and (L.PVP_WEEKLY_TURNIN_TOOLTIP or "This quest is done and can now be turned in.")
                or (L.PVE_EVENTS_ACTIVE_HINT or "This quest is active. Check the quest log for the current objective.")
        end

        return {
            key = "lost_legends",
            label = label,
            text = getActiveQuestStatusText(MIDNIGHT_LOST_LEGENDS_QUEST_ID, readyToTurnIn),
            status = readyToTurnIn and "turnin" or "open",
            seen = true,
            completed = false,
            questID = MIDNIGHT_LOST_LEGENDS_QUEST_ID,
            turnInQuestID = readyToTurnIn and MIDNIGHT_LOST_LEGENDS_QUEST_ID or nil,
            tooltipTitle = (title and title ~= "") and string.format("%s - %s", label, title) or label,
            tooltipLines = tooltipLines,
        }
    end

    local availableLabel = nil
    local visibleOnMap = false
    local visibleQuestIDs = {
        MIDNIGHT_LOST_LEGENDS_RELIC_QUEST_ID,
        MIDNIGHT_LOST_LEGENDS_QUEST_ID,
    }
    for _, questID in ipairs(MIDNIGHT_LOST_LEGENDS_REPEATABLE_POOL) do
        visibleQuestIDs[#visibleQuestIDs + 1] = questID
    end

    for _, questID in ipairs(visibleQuestIDs) do
        visibleOnMap = isTaskQuestVisibleOnAnyMap(questID, { 2413 })
        if visibleOnMap then
            availableLabel = getQuestTitle(questID, label)
            break
        end
    end

    local tooltipLines = {
        L.PVE_EVENTS_LOST_LEGENDS_ACCEPT_HINT or "This weekly becomes available in Harandar during the active Midnight event.",
    }
    if availableLabel then
        tooltipLines[#tooltipLines + 1] = string.format(
            L.PVE_EVENTS_AVAILABLE_HINT or "Currently active: %s",
            availableLabel
        )
    elseif isQuestActive(MIDNIGHT_LOST_LEGENDS_META_QUEST_ID) then
        tooltipLines[#tooltipLines + 1] = L.PVE_EVENTS_WEEKLY_ACTIVE_HINT
            or "This Midnight event is active this week."
    end

    return {
        key = "lost_legends",
        label = label,
        text = L.STATUS_MISSING or "Accept",
        status = "missing",
        seen = availableLabel ~= nil or visibleOnMap or isQuestActive(MIDNIGHT_LOST_LEGENDS_META_QUEST_ID),
        completed = false,
        tooltipTitle = label,
        tooltipLines = tooltipLines,
    }
end
