Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Documentation for this module may be created at Module:Player/doc

local p = {}
local cargo = mw.ext.cargo
local html = mw.html

-- ============================================================
-- HELPER FUNCTIONS
-- ============================================================

-- Currency Formatter
local function formatCurrency(amount)
    if not amount then return "0" end
    local n = tonumber(amount) or 0
    local formatted = tostring(n):reverse():gsub("(%d%d%d)(%d%d%d)","%1,%2"):reverse()
    return '<span class="indian-currency">₹ ' .. formatted .. '</span>'
end

-- Social Icons
local function getSocials(args)
    local container = html.create('div'):addClass('fib-socials')
    local hasSocials = false
    local platforms = {
        {arg='instagram', file='Icon_instagram.png', base='https://www.instagram.com/'},
        {arg='twitter',   file='Icon_twitter.png',   base='https://twitter.com/'},
        {arg='youtube',   file='Icon_youtube.png',   base='https://www.youtube.com/'},
        {arg='discord',   file='Icon_discord.png',   base='https://discord.gg/'},
        {arg='facebook',  file='Icon_facebook.png',  base='https://www.facebook.com/'}
    }
    for _, p in ipairs(platforms) do
        local val = args[p.arg]
        if val and val ~= "" then
            hasSocials = true
            local link
            if val:match("^https?://") then
                link = val
            else
                link = p.base .. val
            end
            container:wikitext('[[File:' .. p.file .. '|24px|link=' .. link .. '|class=social-img]]')
        end
    end
    if hasSocials then return tostring(container) else return "" end
end

-- Rank Lookup
local function getKraftonRank(fullPageName, displayName)
    local sqlFull = fullPageName:gsub("'", "\\'")
    local sqlShort = displayName:gsub("'", "\\'")
    local whereClause = string.format("(BINARY name = '%s' OR BINARY name = '%s') AND type='Player'",sqlFull,sqlShort)
    local results = cargo.query("Krafton_Rankings", "rank", { where = whereClause, limit = 1 })
    if results and #results > 0 then 
        return "#" .. results[1].rank 
    else 
        return "Unranked" 
    end
end

-- ============================================================
-- MAIN 1: PLAYER INFOBOX (WITH EARNINGS BREAKDOWN)
-- ============================================================
function p.infobox(frame)
    local args = frame:getParent().args
    
    -- Variables
    local fullPageName = mw.title.getCurrentTitle().text
    local displayName = args.id or mw.title.getCurrentTitle().subpageText
    local image = args.image or ""
    
    local root = html.create('div'):addClass('flat-infobox')
    
    -- 1. Header
    root:tag('div'):addClass('fib-header')
        :tag('div'):addClass('fib-title'):wikitext(displayName)
    
    -- 2. Image
    local imgContainer = root:tag('div'):addClass('fib-image')
    if image ~= "" then
        imgContainer:wikitext('[[File:' .. image .. '|250px]]')
    else
        imgContainer:wikitext('[[File:Player_Placeholder.png|200px|link=]]')
    end
    
    -- 3. EARNINGS CALCULATION (SEPARATED)
    local individualEarnings = 0
    local teamEarnings = 0
    local sqlNameFull = fullPageName:gsub("'", "\\'")
    local sqlNameShort = displayName:gsub("'", "\\'")

    -- PART A: INDIVIDUAL AWARDS
    if cargo and cargo.query then
        local pWhere = string.format("(player = '%s' OR player = '%s')", sqlNameFull, sqlNameShort)
        local pResults = cargo.query("PrizeMoney", "SUM(prize)=total", { where = pWhere })
        if pResults and #pResults > 0 and pResults[1].total then
            individualEarnings = (tonumber(pResults[1].total) or 0)
        end
    end
    
    -- PART B: TEAM WINNINGS
    if cargo and cargo.query then
        local rosterTable = "Tournament_Teams"
        local rosterFields = "tournament, team"
        local rosterWhere = string.format(
            "p1='%s' OR p1='%s' OR p2='%s' OR p2='%s' OR p3='%s' OR p3='%s' OR p4='%s' OR p4='%s' OR p5='%s' OR p5='%s' OR p6='%s' OR p6='%s'",
            sqlNameFull, sqlNameShort, sqlNameFull, sqlNameShort, sqlNameFull, sqlNameShort,
            sqlNameFull, sqlNameShort, sqlNameFull, sqlNameShort, sqlNameFull, sqlNameShort
        )
        
        local participation = cargo.query(rosterTable, rosterFields, { where = rosterWhere, limit=500 })
        
        if participation and #participation > 0 then
            local prizeConditions = {}
            for _, row in ipairs(participation) do
                if row.tournament and row.team then
                    table.insert(prizeConditions, string.format("(tournament='%s' AND team='%s')", row.tournament:gsub("'", "\\'"), row.team:gsub("'", "\\'")))
                end
            end
            
            if #prizeConditions > 0 then
                local complexWhere = "(" .. table.concat(prizeConditions, " OR ") .. ") AND (player='' OR player IS NULL)"
                local teamPrizes = cargo.query("PrizeMoney", "SUM(prize)=team_total", { where = complexWhere })
                
                if teamPrizes and #teamPrizes > 0 and teamPrizes[1].team_total then
                    teamEarnings = (tonumber(teamPrizes[1].team_total) or 0)
                end
            end
        end
    end

    -- Calculate Total
    local totalEarnings = individualEarnings + teamEarnings

    -- 4. Status & Rank Grid
    local statusColor = "#333"
    local statusText = args.status or "Active"
    if args.status then
        local s = args.status:lower()
        if s == "active" then statusColor = "#16a34a"
        elseif s == "inactive" or s == "banned" or s == "retired" then statusColor = "#dc2626"
        end
    end
    
    local grid1 = root:tag('div'):addClass('fib-grid')
    grid1:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Status'):done():tag('div'):addClass('fib-value-sm'):css('color', statusColor):wikitext(statusText):done()
    
    local rankVal = getKraftonRank(fullPageName, displayName)
    grid1:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Krafton Rank'):done():tag('div'):addClass('fib-value-sm'):wikitext(rankVal):done()

    -- 5. Role & Nation Grid
    local grid2 = root:tag('div'):addClass('fib-grid')
    grid2:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Nationality'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.nationality or 'India'):done()
    grid2:tag('div'):addClass('fib-cell'):tag('div'):addClass('fib-label-sm'):wikitext('Role'):done():tag('div'):addClass('fib-value-sm'):wikitext(args.role or 'Player'):done()

    -- 6. Earnings (Highlight WITH BREAKDOWN)
    if totalEarnings > 0 then
        local prizeBox = root:tag('div'):addClass('fib-prize')
        
        -- Main Total
        prizeBox:tag('div'):addClass('fib-label-sm'):wikitext('Approx. Earnings'):done()
        prizeBox:tag('div'):addClass('fib-prize-val'):wikitext(formatCurrency(totalEarnings)):done()
        
        -- Breakdown Sub-Section
        local breakdown = prizeBox:tag('div')
            :css('display', 'flex')
            :css('justify-content', 'space-between')
            :css('margin-top', '8px')
            :css('padding-top', '6px')
            :css('border-top', '1px solid rgba(0,0,0,0.08)')
        
        -- Team Winnings (Left)
        local tDiv = breakdown:tag('div'):css('text-align', 'left')
        tDiv:tag('div'):css('font-size', '0.65em'):css('text-transform', 'uppercase'):css('opacity', '0.7'):wikitext('Team'):done()
        tDiv:tag('div'):css('font-size', '0.85em'):css('font-weight', '600'):wikitext(formatCurrency(teamEarnings)):done()
        
        -- Individual Winnings (Right)
        local iDiv = breakdown:tag('div'):css('text-align', 'right')
        iDiv:tag('div'):css('font-size', '0.65em'):css('text-transform', 'uppercase'):css('opacity', '0.7'):wikitext('Individual'):done()
        iDiv:tag('div'):css('font-size', '0.85em'):css('font-weight', '600'):wikitext(formatCurrency(individualEarnings)):done()
    end
    
    -- 7. Info List
    local list = root:tag('div'):addClass('fib-list')
    local function addRow(label, value)
        if value and value ~= "" then
            list:tag('div'):addClass('fib-row'):tag('div'):addClass('fib-label'):wikitext(label):done():tag('div'):addClass('fib-data'):wikitext(value):done()
        end
    end
    
    addRow('Real Name', args.real_name)
    addRow('Born', args.birth_date)
    if args.current_team then
        addRow('Current Team', '[[' .. args.current_team .. ']]') 
    end
    addRow('Game', args.game or "BGMI")

    -- 8. Team History
    local history = cargo.query("Player_Former_Teams", "team, join_date, leave_date", { 
        where = "player_id = '" .. fullPageName:gsub("'", "\\'") .. "'",
        orderBy = "join_date DESC",
        limit = 10 
    })
    
    if #history > 0 then
        list:tag('div'):addClass('fib-header'):css('font-size','0.95em'):css('padding','10px'):css('margin-top','15px'):css('border-radius','6px'):wikitext('Team History')
        local histTable = list:tag('table'):css('width','100%'):css('font-size','0.9em'):css('border-collapse','collapse'):css('margin-top','5px')
        
        for _, hRow in ipairs(history) do
            local tr = histTable:tag('tr'):css('border-bottom','1px solid #e2e8f0')
            tr:tag('td'):css('padding','8px 4px'):css('font-weight','600'):wikitext('[[' .. hRow.team .. ']]')
            local dates = (hRow.join_date and mw.getContentLanguage():formatDate('M y', hRow.join_date) or '?') .. ' – ' .. (hRow.leave_date and mw.getContentLanguage():formatDate('M y', hRow.leave_date) or 'Now')
            tr:tag('td'):css('text-align','right'):css('padding','8px 4px'):css('color','#64748b'):wikitext(dates)
        end
    else
        -- Fallback check for short name
        local historyShort = cargo.query("Player_Former_Teams", "team, join_date, leave_date", { 
            where = "player_id = '" .. displayName:gsub("'", "\\'") .. "'",
            orderBy = "join_date DESC",
            limit = 10 
        })
        if #historyShort > 0 then
            list:tag('div'):addClass('fib-header'):css('font-size','0.95em'):css('padding','10px'):css('margin-top','15px'):css('border-radius','6px'):wikitext('Team History')
            local histTable = list:tag('table'):css('width','100%'):css('font-size','0.9em'):css('border-collapse','collapse'):css('margin-top','5px')
            for _, hRow in ipairs(historyShort) do
                local tr = histTable:tag('tr'):css('border-bottom','1px solid #e2e8f0')
                tr:tag('td'):css('padding','8px 4px'):css('font-weight','600'):wikitext('[[' .. hRow.team .. ']]')
                local dates = (hRow.join_date and mw.getContentLanguage():formatDate('M y', hRow.join_date) or '?') .. ' – ' .. (hRow.leave_date and mw.getContentLanguage():formatDate('M y', hRow.leave_date) or 'Now')
                tr:tag('td'):css('text-align','right'):css('padding','8px 4px'):css('color','#64748b'):wikitext(dates)
            end
        end
    end

    -- 9. Socials
    root:wikitext(getSocials(args))

    return tostring(root)
end

-- ============================================================
-- MAIN 2: FORMER PLAYERS TABLE
-- ============================================================
function p.formerPlayers(frame)
    local args = frame:getParent().args
    local team = args.team or mw.title.getCurrentTitle().text
    
    local results = cargo.query("Player_Former_Teams, Players", "Player_Former_Teams.player_id=id, Players.real_name=Name, Player_Former_Teams.role=role, Player_Former_Teams.join_date=join_date, Player_Former_Teams.leave_date=leave_date", {
        joinOn = "Player_Former_Teams.player_id = Players._pageName",
        where = "Player_Former_Teams.team = '" .. team:gsub("'", "\\'") .. "' AND Player_Former_Teams.leave_date != ''",
        orderBy = "Player_Former_Teams.leave_date DESC"
    })
    
    local root = html.create('table'):addClass('wikitable flat-table sortable'):css('width','100%')
    local header = root:tag('tr')
    header:tag('th'):wikitext('ID'); header:tag('th'):wikitext('Name'); header:tag('th'):wikitext('Role'); header:tag('th'):wikitext('Duration')
    
    if #results > 0 then
        for _, row in ipairs(results) do
            local tr = root:tag('tr')
            tr:tag('td'):css('font-weight','bold'):wikitext('[[' .. row.id .. ']]')
            tr:tag('td'):wikitext(row.Name)
            tr:tag('td'):wikitext(row.role)
            local range = (row.join_date and mw.getContentLanguage():formatDate('M Y', row.join_date) or '?') .. ' – ' .. (row.leave_date and mw.getContentLanguage():formatDate('M Y', row.leave_date) or '?')
            tr:tag('td'):attr('data-sort-value', row.leave_date):wikitext(range)
        end
    else
        return '<div style="font-style:italic; color:#64748b; padding:10px;">No former players found for this team.</div>'
    end
    
    return tostring(root)
end

return p