--[[
InspectionState.lua - Mr. Mythical Gear Check inspection state helpers

Purpose: Persistent scan state and inspection status reporting.
Dependencies: GearUtils, GearData, InspectionUnits
Author: Braunerr
--]]

local MrMythicalGearCheck = MrMythicalGearCheck or {}
MrMythicalGearCheck.InspectionState = MrMythicalGearCheck.InspectionState or {}

local InspectionState = MrMythicalGearCheck.InspectionState

InspectionState.groupScanState = InspectionState.groupScanState or {}

local function getDependency(name)
    return (_G.MrMythicalGearCheck and _G.MrMythicalGearCheck[name]) or MrMythicalGearCheck[name]
end

local function getUnitDisplayName(unit)
    local InspectionUnits = getDependency("InspectionUnits")
    if InspectionUnits and InspectionUnits.GetUnitFullName then
        return InspectionUnits:GetUnitFullName(unit) or UnitName(unit)
    end
    return UnitName(unit)
end

local function findScanDataForName(playerName)
    local scanData = InspectionState.groupScanState[playerName]
    if scanData then
        return scanData, playerName
    end

    local InspectionUnits = getDependency("InspectionUnits")
    if not InspectionUnits or not InspectionUnits.NamesMatch then
        return nil, playerName
    end

    for storedName, storedData in pairs(InspectionState.groupScanState) do
        if InspectionUnits:NamesMatch(storedName, playerName) then
            return storedData, storedName
        end
    end

    return nil, playerName
end

--- Creates a brief summary for an inspected player
--- @param unit string Unit ID
--- @param playerName string Player name
--- @param gearInfo table|nil Optional cached gear info
--- @return string Brief summary of player's gear status
--- @return table|nil Detail payload with gearDetails / summaryLines / totalIssues
function InspectionState:CreatePlayerSummary(unit, playerName, gearInfo)
    local GearUtils = getDependency("GearUtils")
    if not GearUtils then
        return nil, nil
    end

    -- Detailed analysis returns nil while inspect links are still loading.
    local analysis = GearUtils:AnalyzeGear(unit, "detailed")
    if not analysis then
        return nil, nil
    end

    local avgItemLevel = analysis.avgItemLevel
    if not avgItemLevel or avgItemLevel == 0 then
        local itemLevel = 0
        local itemCount = 0
        local gearData = getDependency("GearData")
        if gearData and gearData.SLOT_NAMES then
            for slotId, _ in pairs(gearData.SLOT_NAMES) do
                local itemLink = GetInventoryItemLink(unit, slotId)
                if itemLink then
                    local itemLvl = C_Item and C_Item.GetDetailedItemLevelInfo and C_Item.GetDetailedItemLevelInfo(itemLink)
                    if itemLvl and itemLvl > 0 then
                        itemLevel = itemLevel + itemLvl
                        itemCount = itemCount + 1
                    end
                end
            end
        end
        avgItemLevel = itemCount > 0 and math.floor(itemLevel / itemCount) or 0
    end
    local className, classFile = UnitClass(unit)

    local details = {
        gearDetails = analysis.gearDetails or {},
        summaryLines = analysis.summaryLines or {},
        totalIssues = analysis.totalIssues or 0,
        avgItemLevel = avgItemLevel,
        className = className,
        classFile = classFile,
        emptySlots = analysis.emptySlots or 0,
        unenchantedItems = analysis.unenchantedItems or 0,
        lowRankEnchants = analysis.lowRankEnchants or 0,
        emptyGems = analysis.emptyGems or 0,
        lowRankGems = analysis.lowRankGems or 0,
        suboptimalGems = analysis.suboptimalGems or 0,
        hasLowDurability = analysis.hasLowDurability and true or false,
        lowItemLevelPieces = analysis.lowItemLevelPieces or 0,
        wrongStatEnchants = analysis.wrongStatEnchants or 0,
        wrongStatGems = analysis.wrongStatGems or 0,
        lowAvgItemLevel = analysis.lowAvgItemLevel and true or false,
        embellishmentIssues = analysis.embellishmentIssues and true or false,
        embellishmentCount = analysis.embellishmentCount or 0,
    }

    if analysis.totalIssues == 0 then
        return string.format("iLvl %d - |cff00ff00PERFECT GEAR|r", avgItemLevel), details
    end

    local issueTypes = {}
    if analysis.emptySlots > 0 then
        table.insert(issueTypes, analysis.emptySlots .. " empty slots")
    end
    if analysis.unenchantedItems > 0 then
        table.insert(issueTypes, analysis.unenchantedItems .. " missing enchants")
    end
    if analysis.lowRankEnchants > 0 then
        table.insert(issueTypes, analysis.lowRankEnchants .. " enchant issues")
    end
    if analysis.emptyGems > 0 then
        table.insert(issueTypes, analysis.emptyGems .. " empty gems")
    end
    if analysis.lowRankGems > 0 then
        table.insert(issueTypes, analysis.lowRankGems .. " gem issues")
    end
    if analysis.suboptimalGems and analysis.suboptimalGems > 0 then
        table.insert(issueTypes, analysis.suboptimalGems .. " suboptimal gems")
    end
    if analysis.hasLowDurability then
        table.insert(issueTypes, "needs repair")
    end
    if analysis.lowItemLevelPieces and analysis.lowItemLevelPieces > 0 then
        table.insert(issueTypes, analysis.lowItemLevelPieces .. " low ilvl")
    end
    if analysis.lowAvgItemLevel then
        table.insert(issueTypes, "low average ilvl")
    end
    if analysis.wrongStatEnchants and analysis.wrongStatEnchants > 0 then
        table.insert(issueTypes, analysis.wrongStatEnchants .. " wrong-stat enchants")
    end
    if analysis.wrongStatGems and analysis.wrongStatGems > 0 then
        table.insert(issueTypes, analysis.wrongStatGems .. " wrong-stat gems")
    end
    if analysis.embellishmentIssues then
        table.insert(issueTypes, "embellishments")
    end

    local issueText = table.concat(issueTypes, ", ")
    return string.format("iLvl %d - |cffff8000%d ISSUES|r (%s)", avgItemLevel, analysis.totalIssues, issueText), details
end

--- Gets list of failed inspections (members that need scanning)
--- @return table List of members that haven't been successfully scanned
function InspectionState:GetFailedInspectionsList()
    local failedList = {}
    local InspectionUnits = getDependency("InspectionUnits")
    local groupMembers = InspectionUnits and InspectionUnits:GetGroupMembers() or {}

    for _, unit in ipairs(groupMembers) do
        local playerName = getUnitDisplayName(unit)
        if playerName then
            local scanState = findScanDataForName(playerName)
            if not scanState or scanState.hasData ~= true then
                table.insert(failedList, {
                    name = playerName,
                    unit = unit,
                    reason = scanState and scanState.reason or "Not scanned",
                    retryCount = scanState and scanState.retryCount or 0
                })
            end
        end
    end

    return failedList
end

--- Clears scan state for current group members (for fresh scan)
function InspectionState:ClearGroupScanState()
    local InspectionUnits = getDependency("InspectionUnits")
    local groupMembers = InspectionUnits and InspectionUnits:GetGroupMembers() or {}
    for _, unit in ipairs(groupMembers) do
        local playerName = getUnitDisplayName(unit)
        if playerName then
            local _, storedKey = findScanDataForName(playerName)
            if storedKey then
                self.groupScanState[storedKey] = nil
            end
            self.groupScanState[playerName] = nil
        end
    end
end

--- Gets current inspection status for UI display
--- @param scanQueue table|nil Current scan queue
--- @return table Current inspection status
function InspectionState:GetInspectionStatus(scanQueue)
    local InspectionUnits = getDependency("InspectionUnits")
    local groupMembers = InspectionUnits and InspectionUnits:GetGroupMembers() or {}
    local memberReports = {}
    local failedCount = 0

    for _, unit in ipairs(groupMembers) do
        local playerName = getUnitDisplayName(unit)
        if playerName then
            local className, classFile = UnitClass(unit)
            local scanData = findScanDataForName(playerName)
            if scanData and scanData.hasData then
                local details = scanData.details or {}
                if not details.className then
                    details.className = className
                    details.classFile = classFile
                end
                table.insert(memberReports, {
                    name = playerName,
                    unit = unit,
                    summary = scanData.summary,
                    details = details,
                    hasData = true,
                    reason = scanData.reason
                })
            else
                local summary = "Not scanned"
                local reason = nil
                if scanData and scanData.summary then
                    summary = scanData.summary
                end
                if scanData and scanData.reason then
                    reason = scanData.reason
                    if not scanData.summary then
                        summary = "Failed - " .. reason
                    end
                end
                table.insert(memberReports, {
                    name = playerName,
                    unit = unit,
                    summary = summary,
                    details = scanData and scanData.details or {
                        className = className,
                        classFile = classFile,
                        totalIssues = 0,
                    },
                    hasData = false,
                    reason = reason
                })
                failedCount = failedCount + 1
            end
        end
    end

    return {
        hasResults = #memberReports > 0,
        totalMembers = #groupMembers,
        inspectedMembers = #memberReports - failedCount,
        failedCount = failedCount,
        canRescan = failedCount > 0 and not InCombatLockdown(),
        memberReports = memberReports,
        failedInspections = self:GetFailedInspectionsList(),
        queuedCount = scanQueue and #scanQueue or 0,
        scanQueue = scanQueue or {}
    }
end
