local addonName, addonTable = ...
---@type MK
local MK = addonTable.MK
local core = addonTable
local TRANSLATE = core.TRANSLATE or function(msg) return msg end
local AccountType = core.AccountType or {}

local ACCOUNT_TYPE_PENDING_SPINNER_SIZE = 18
local ACCOUNT_TYPE_BLACKLIST_ICON_TEXTURE = (core.MK_ICON_PATH or ("Interface\\AddOns\\" .. addonName .. "\\Art\\Ui\\Icon\\")) .. "Blacklist.png"
local ACCOUNT_TYPE_LEAVER_ICON_TEXTURE = (core.MK_ICON_PATH or ("Interface\\AddOns\\" .. addonName .. "\\Art\\Ui\\Icon\\")) .. "isLeaver.png"
local ACCOUNT_TYPE_LEAVER_TEXT_COLOR = { 1, 0.08, 0.05, 1 }

local function StopGroupAccountTypePendingAnimation(accountTypeContainer)
    if not accountTypeContainer then
        return
    end

    local spinner = accountTypeContainer.mkAccountTypePendingSpinner
    if spinner then
        if spinner.Anim and spinner.Anim.Stop then
            spinner.Anim:Stop()
        end
        spinner:Hide()
    end
end

local function CreateFallbackGroupAccountTypeSpinner(parent)
    if not (CreateFrame and parent) then
        return nil
    end

    local spinner = CreateFrame("Frame", nil, parent)
    spinner.Ring = spinner:CreateTexture(nil, "ARTWORK")
    spinner.Ring:SetAllPoints(spinner)
    spinner.Ring:SetAtlas("Spinner_Ring")
    spinner.Sparks = spinner:CreateTexture(nil, "ARTWORK")
    spinner.Sparks:SetAllPoints(spinner)
    spinner.Sparks:SetAtlas("Spinner_Sparks")
    if spinner.Sparks.SetBlendMode then
        spinner.Sparks:SetBlendMode("ADD")
    end

    return spinner
end

local function GetGroupAccountTypePendingSpinner(accountTypeContainer)
    if not (accountTypeContainer and CreateFrame) then
        return nil
    end

    local spinner = accountTypeContainer.mkAccountTypePendingSpinner
    if spinner then
        return spinner
    end

    local ok, nativeSpinner = pcall(CreateFrame, "Frame", nil, accountTypeContainer, "SpinnerTemplate")
    spinner = ok and nativeSpinner or CreateFallbackGroupAccountTypeSpinner(accountTypeContainer)
    if not spinner then
        return nil
    end

    if spinner.SetFrameLevel and accountTypeContainer.GetFrameLevel then
        spinner:SetFrameLevel((accountTypeContainer:GetFrameLevel() or 0) + 2)
    end
    spinner:Hide()
    accountTypeContainer.mkAccountTypePendingSpinner = spinner
    return spinner
end

local function StartGroupAccountTypePendingAnimation(accountTypeContainer, accountTypeLabel, align, insetX, centerLabel)
    local spinner = GetGroupAccountTypePendingSpinner(accountTypeContainer)
    if not spinner then
        if accountTypeLabel then
            accountTypeLabel:SetText("")
        end
        return false
    end

    if accountTypeLabel then
        accountTypeLabel:SetText("")
    end

    insetX = tonumber(insetX) or 0
    spinner:ClearAllPoints()
    spinner:SetSize(ACCOUNT_TYPE_PENDING_SPINNER_SIZE, ACCOUNT_TYPE_PENDING_SPINNER_SIZE)
    if align == "LEFT" and centerLabel ~= true then
        spinner:SetPoint("LEFT", accountTypeContainer, "LEFT", insetX, 0)
    else
        spinner:SetPoint("CENTER", accountTypeContainer, "CENTER", 0, 0)
    end
    spinner:Show()
    if spinner.Anim and spinner.Anim.Play and (not spinner.Anim.IsPlaying or not spinner.Anim:IsPlaying()) then
        spinner.Anim:Play()
    end
    return true
end

local function HideGroupAccountTypeIconSlot(accountTypeContainer)
    local iconSlot = accountTypeContainer and accountTypeContainer.mkAccountTypeIconSlot
    if iconSlot then
        iconSlot:Hide()
    end
end

local function HideGroupAccountTypeExtraIcons(accountTypeContainer)
    local extraIcons = accountTypeContainer and accountTypeContainer.mkAccountTypeExtraIcons
    if type(extraIcons) ~= "table" then
        return
    end

    for _, icon in ipairs(extraIcons) do
        icon:Hide()
    end
end

local function GetGroupAccountTypeIconSlot(accountTypeContainer, iconSlotSize, align, insetX)
    local iconSlot = accountTypeContainer and accountTypeContainer.mkAccountTypeIconSlot
    iconSlotSize = tonumber(iconSlotSize)
    if not (iconSlot and iconSlotSize and iconSlotSize > 0) then
        return nil
    end

    insetX = tonumber(insetX) or 0
    iconSlot:ClearAllPoints()
    iconSlot:SetSize(iconSlotSize, iconSlotSize)
    if align == "LEFT" then
        iconSlot:SetPoint("LEFT", accountTypeContainer, "LEFT", insetX, 0)
    else
        iconSlot:SetPoint("CENTER", accountTypeContainer, "CENTER", 0, 0)
    end
    iconSlot:Show()
    return iconSlot
end

local function SetGroupAccountTypeText(accountTypeIcon, accountTypeLabel, accountTypeContainer, text, textColor, align, insetX, centerLabel, pendingAnimation)
    if accountTypeIcon then
        accountTypeIcon:Hide()
    end
    HideGroupAccountTypeIconSlot(accountTypeContainer)
    HideGroupAccountTypeExtraIcons(accountTypeContainer)
    if not accountTypeLabel then
        return false
    end

    textColor = textColor or { 0.58, 0.58, 0.58, 1 }
    local containerWidth = (accountTypeContainer and accountTypeContainer.GetWidth and accountTypeContainer:GetWidth()) or core.GROUP_LIST_COLUMN_WIDTHS.accountType or 120
    insetX = tonumber(insetX) or 0

    accountTypeLabel:ClearAllPoints()
    if align == "LEFT" and centerLabel ~= true then
        accountTypeLabel:SetPoint("LEFT", accountTypeContainer, "LEFT", insetX, 0)
        accountTypeLabel:SetJustifyH("LEFT")
        accountTypeLabel:SetWidth(math.max(1, containerWidth - insetX))
    else
        accountTypeLabel:SetPoint("CENTER", accountTypeContainer, "CENTER", 0, 0)
        accountTypeLabel:SetJustifyH("CENTER")
        accountTypeLabel:SetWidth(containerWidth)
    end
    accountTypeLabel:SetHeight(18)
    accountTypeLabel:SetTextColor(textColor[1] or 0.58, textColor[2] or 0.58, textColor[3] or 0.58, textColor[4] or 1)
    if pendingAnimation == true then
        StartGroupAccountTypePendingAnimation(accountTypeContainer, accountTypeLabel, align, insetX, centerLabel)
    else
        StopGroupAccountTypePendingAnimation(accountTypeContainer)
        accountTypeLabel:SetText(TRANSLATE(text or ""))
    end
    return true
end

local function SetGroupAccountTypeIconText(accountTypeIcon, accountTypeLabel, accountTypeContainer, texture, text, textColor, iconSize, iconGap, align, insetX, iconSlotSize, centerLabel)
    if not accountTypeIcon or not accountTypeLabel then
        return false
    end

    HideGroupAccountTypeExtraIcons(accountTypeContainer)
    StopGroupAccountTypePendingAnimation(accountTypeContainer)
    iconSize = iconSize or 16
    iconGap = iconGap or 3
    insetX = tonumber(insetX) or 0
    textColor = textColor or { 1, 0.82, 0, 1 }

    accountTypeIcon:SetTexture(texture)
    accountTypeIcon:SetTexCoord(0, 1, 0, 1)
    accountTypeIcon:SetSize(iconSize, iconSize)

    local containerWidth = (accountTypeContainer and accountTypeContainer.GetWidth and accountTypeContainer:GetWidth()) or core.GROUP_LIST_COLUMN_WIDTHS.accountType or 120
    local effectiveIconWidth = tonumber(iconSlotSize) or iconSize
    local centeredReserveWidth = 0
    if centerLabel == true and accountTypeContainer and accountTypeContainer.mkAccountTypeReserveCenteredLabelIconSpace == true then
        centeredReserveWidth = math.max(0, effectiveIconWidth + iconGap + insetX)
    end
    local maxLabelWidth = centerLabel == true
        and math.max(1, containerWidth - centeredReserveWidth * 2)
        or math.max(1, containerWidth - effectiveIconWidth - iconGap - insetX)

    accountTypeLabel:ClearAllPoints()
    accountTypeLabel:SetWidth(maxLabelWidth)
    accountTypeLabel:SetText(TRANSLATE(text or ""))
    accountTypeLabel:SetTextColor(textColor[1] or 1, textColor[2] or 0.82, textColor[3] or 0, textColor[4] or 1)
    accountTypeLabel:SetJustifyH(centerLabel == true and "CENTER" or "LEFT")
    accountTypeLabel:SetHeight(18)

    local labelWidth = centerLabel == true and maxLabelWidth or math.min(accountTypeLabel:GetStringWidth() or 28, maxLabelWidth)
    accountTypeLabel:SetWidth(labelWidth)

    local totalWidth = effectiveIconWidth + iconGap + labelWidth
    local iconSlot = GetGroupAccountTypeIconSlot(accountTypeContainer, iconSlotSize, align, insetX)
    accountTypeIcon:ClearAllPoints()
    if iconSlot then
        accountTypeIcon:SetPoint("CENTER", iconSlot, "CENTER", 0, 0)
    elseif align == "LEFT" then
        accountTypeIcon:SetPoint("LEFT", accountTypeContainer, "LEFT", insetX, 0)
    else
        accountTypeIcon:SetPoint("LEFT", accountTypeContainer, "CENTER", -totalWidth / 2, 0)
    end
    accountTypeLabel:ClearAllPoints()
    if centerLabel == true then
        accountTypeLabel:SetPoint("CENTER", accountTypeContainer, "CENTER", 0, 0)
    else
        accountTypeLabel:SetPoint("LEFT", iconSlot or accountTypeIcon, "RIGHT", iconGap, 0)
    end
    accountTypeIcon:Show()
    return true
end

local function GetGroupAccountTypeDisplayText(accountTypeInfo, character)
    local text = accountTypeInfo and accountTypeInfo.text
    if
        character
        and (character.mkCompactMeetingStoneAccountTypeText == true or character.mkCompactLeaderAccountTypeText == true)
        and type(text) == "string"
    then
        local compactText = accountTypeInfo.compactText or text:gsub("^火车头%s*", ""):gsub("^大秘%s*", "")
        if compactText ~= "" then
            return compactText
        end
    end

    return text
end

local function GetGroupAccountTypeLocalInfo(character)
    if not (type(character) == "table" and character.mkAccountTypeUnavailable == true) then
        return nil
    end

    local text = TRANSLATE(character.mkAccountTypeUnavailableText or "无法查询")
    return {
        status = "unavailable",
        text = text,
        compactText = text,
        textColor = character.mkAccountTypeUnavailableTextColor or ACCOUNT_TYPE_LEAVER_TEXT_COLOR,
        badges = {},
    }
end

local function GetGroupAccountTypeIconSizeOverride(character, accountTypeKey)
    if type(character) ~= "table" then
        return nil
    end

    local iconSizes = character.mkAccountTypeIconSizes
    if type(iconSizes) == "table" and accountTypeKey then
        local iconSize = iconSizes[accountTypeKey]
        if type(iconSize) == "number" then
            return iconSize
        end
    end

    return character.mkAccountTypeIconSize
end

local function GetGroupAccountTypeQueryName(characterEntry, character)
    local name = character and character.name or characterEntry and characterEntry.key
    local realm = character and character.realm or nil
    if type(name) == "string" and name:find("-", 1, true) and (type(realm) ~= "string" or realm == "") then
        local shortName, fullRealm = strsplit("-", name)
        name = shortName or name
        realm = fullRealm
    end

    return name, realm
end

function MK:SetGroupAccountTypeIcon(row, characterEntry, displayState)
    if not row or not row.widgets or not row.widgets.accountTypeIcon then
        return
    end

    local accountTypeIcon = row.widgets.accountTypeIcon
    local accountTypeLabel = row.widgets.accountTypeLabel
    local accountTypeContainer = row.widgets.accountTypeContainer
    StopGroupAccountTypePendingAnimation(accountTypeContainer)
    accountTypeIcon:Hide()
    accountTypeIcon:ClearAllPoints()
    accountTypeIcon:SetPoint("CENTER", accountTypeContainer or row, "CENTER", 0, 0)
    HideGroupAccountTypeIconSlot(accountTypeContainer)
    HideGroupAccountTypeExtraIcons(accountTypeContainer)

    if accountTypeLabel then
        accountTypeLabel:ClearAllPoints()
        accountTypeLabel:SetPoint("CENTER", accountTypeContainer or row, "CENTER", 0, 0)
        accountTypeLabel:SetWidth((accountTypeContainer and accountTypeContainer.GetWidth and accountTypeContainer:GetWidth()) or 1)
        accountTypeLabel:SetHeight(18)
        accountTypeLabel:SetJustifyH("CENTER")
        accountTypeLabel:SetTextColor(1, 1, 1, 1)
        accountTypeLabel:SetText("")
    end

    local character = characterEntry and characterEntry.data or nil
    if type(character) ~= "table" then
        return
    end
    local accountTypeAlign = character.mkAccountTypeAlign or (accountTypeContainer and accountTypeContainer.mkAccountTypeAlign)
    local accountTypeInsetX = character.mkAccountTypeInsetX
    if accountTypeInsetX == nil and accountTypeContainer then
        accountTypeInsetX = accountTypeContainer.mkAccountTypeInsetX
    end
    local accountTypeIconSlotSize = character.mkAccountTypeIconSlotSize or (accountTypeContainer and accountTypeContainer.mkAccountTypeIconSlotSize)
    local accountTypeCenterLabel = character.mkAccountTypeCenterLabel
    if accountTypeCenterLabel == nil and accountTypeContainer then
        accountTypeCenterLabel = accountTypeContainer.mkAccountTypeCenterLabel
    end
    accountTypeCenterLabel = accountTypeCenterLabel == true

    local isCarpoolEntry = displayState and displayState.isCarpoolEntry == true
    local unitStatus = AccountType.ResolveUnitStatus and AccountType.ResolveUnitStatus({
        characterEntry = characterEntry,
        isOffline = (characterEntry.isOffline == true or character.isOffline == true),
        isLeaver = character.isLeaver == true,
    }, {
        includeOffline = not isCarpoolEntry,
        includeBlacklist = true,
        includeLeaver = true,
        includeAccount = false,
    }) or nil

    if unitStatus and unitStatus.status == "offline" then
        SetGroupAccountTypeText(
            accountTypeIcon,
            accountTypeLabel,
            accountTypeContainer or row,
            TRANSLATE(core.GROUP_LIST_ACCOUNT_TYPE_OFFLINE_TEXT or "离线"),
            core.GROUP_LIST_ACCOUNT_TYPE_OFFLINE_TEXT_COLOR or { 0.52, 0.52, 0.52, 1 },
            accountTypeAlign,
            accountTypeInsetX,
            accountTypeCenterLabel
        )
        return
    end

    if unitStatus and unitStatus.status == "blacklist" then
        local accountTypeIconSizeOverride = GetGroupAccountTypeIconSizeOverride(character, "blacklist")
        SetGroupAccountTypeIconText(
            accountTypeIcon,
            accountTypeLabel,
            accountTypeContainer or row,
            ACCOUNT_TYPE_BLACKLIST_ICON_TEXTURE,
            "屏蔽",
            ACCOUNT_TYPE_LEAVER_TEXT_COLOR,
            accountTypeIconSizeOverride or 18,
            core.GROUP_LIST_ACCOUNT_TYPE_VETERAN_GAP or 3,
            accountTypeAlign,
            accountTypeInsetX,
            accountTypeIconSlotSize,
            accountTypeCenterLabel
        )
        return
    end

    if unitStatus and unitStatus.status == "leaver" then
        local accountTypeIconSizeOverride = GetGroupAccountTypeIconSizeOverride(character, "leaver")
        SetGroupAccountTypeIconText(
            accountTypeIcon,
            accountTypeLabel,
            accountTypeContainer or row,
            ACCOUNT_TYPE_LEAVER_ICON_TEXTURE,
            "逃兵",
            ACCOUNT_TYPE_LEAVER_TEXT_COLOR,
            accountTypeIconSizeOverride or 18,
            core.GROUP_LIST_ACCOUNT_TYPE_VETERAN_GAP or 3,
            accountTypeAlign,
            accountTypeInsetX,
            accountTypeIconSlotSize,
            accountTypeCenterLabel
        )
        return
    end

    local accountTypeInfo = GetGroupAccountTypeLocalInfo(character)
    if accountTypeInfo then
        SetGroupAccountTypeText(
            accountTypeIcon,
            accountTypeLabel,
            accountTypeContainer or row,
            accountTypeInfo.text,
            accountTypeInfo.textColor,
            accountTypeAlign,
            accountTypeInsetX,
            accountTypeCenterLabel
        )
        return
    end

    local name, realm
    if AccountType.GetIdentityFromCharacterEntry then
        name, realm = AccountType.GetIdentityFromCharacterEntry(characterEntry)
    else
        name, realm = GetGroupAccountTypeQueryName(characterEntry, character)
    end
    -- 查询由 GroupList/Applicant/FindGroup 的批处理入口统一发起；渲染函数只读缓存，避免滚动/刷新时重复排队。
    local accountState = AccountType.GetAccountState and AccountType.GetAccountState(name, realm, {
        includeVeteran = true,
    }) or nil
    accountTypeInfo = accountState and accountState.accountTypeInfo or nil
    if not accountTypeInfo or accountTypeInfo.status == "unknown" then
        return
    end
    if accountTypeInfo.status == "pending" then
        SetGroupAccountTypeText(
            accountTypeIcon,
            accountTypeLabel,
            accountTypeContainer or row,
            accountTypeInfo.text,
            accountTypeInfo.textColor,
            accountTypeAlign,
            accountTypeInsetX,
            accountTypeCenterLabel,
            true
        )
        return
    end
    if accountTypeInfo.status == "no_response" then
        SetGroupAccountTypeText(
            accountTypeIcon,
            accountTypeLabel,
            accountTypeContainer or row,
            accountTypeInfo.text,
            accountTypeInfo.textColor,
            accountTypeAlign,
            accountTypeInsetX,
            accountTypeCenterLabel
        )
        return
    end
    local accountTypeKey = accountState and accountState.status or nil
    local accountTypeIconSizeOverride = GetGroupAccountTypeIconSizeOverride(character, accountTypeKey)

    if not accountTypeInfo.texture then
        return
    end

    local displayText = GetGroupAccountTypeDisplayText(accountTypeInfo, character)
    SetGroupAccountTypeIconText(
        accountTypeIcon,
        accountTypeLabel,
        accountTypeContainer or row,
        accountTypeInfo.texture,
        displayText,
        accountTypeInfo.textColor,
        accountTypeIconSizeOverride or accountTypeInfo.width or 16,
        accountTypeInfo.gap or core.GROUP_LIST_ACCOUNT_TYPE_VETERAN_GAP or 3,
        accountTypeAlign,
        accountTypeInsetX,
        accountTypeIconSlotSize,
        accountTypeCenterLabel
    )
end
