# ----------------------------------------------------------------
# Scenario 5: Contributor Growth System
# Flow: Collect data -> Calculate scores -> Generate HTML -> Publish Wiki -> Award badges
#
# Scoring (AHP weight model):
#   - Issues Created:   15% weight (issue +list)
#   - PRs Merged:       25% weight (pr +list state=merged)
#   - Code Changes:     30% weight (pr +files)
#   - Issue Comments:   15% weight (issue +view)
#   - Team Member:      15% weight (repo +members)
#
# Badges:
#   - Champion          >= 80
#   - Core Contributor  >= 60
#   - Active Contributor >= 40
#   - Contributor       >= 20
#   - Newcomer          < 20
# ----------------------------------------------------------------
#Requires -Version 5.1

param(
    [string]$Owner = "",
    [string]$Repo = "",
    [int]$Sample = 10,
    [switch]$Award,
    [switch]$DryRun,
    [switch]$Help
)

$ErrorActionPreference = "Stop"
Import-Module "$PSScriptRoot/lib/common.psm1" -Force -WarningAction SilentlyContinue

if ($Help) {
    Write-Host "Usage: powershell 05-contributor-growth.ps1 -Owner OWNER -Repo REPO [-Sample N] [-Award] [-DryRun]"
    Write-Host ""
    Write-Host "  -Owner OWNER      Repository owner"
    Write-Host "  -Repo  REPO       Repository name"
    Write-Host "  -Sample N         Sample N PRs for code stats (default: 10)"
    Write-Host "  -Award            Auto-create badge award issues"
    Write-Host "  -DryRun           Preview actions without executing"
    exit 0
}

Check-Auth
$r = Resolve-OwnerRepo $Owner $Repo
$Owner = $r.Owner; $Repo = $r.Repo

$reportFile = "contrib-report-$Owner-$Repo.html"

# ----------------------------------------------------------------
Log-Title "Contributor Growth System: $Owner/$Repo"
# ----------------------------------------------------------------

# -- Step 1: Collect Data --
Log-Step "Collecting data..."

$issuesOpen = Invoke-GLCheck "issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "100"
$issuesClosed = Invoke-GLCheck "issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "closed", "--limit", "100"
$openCount = if ($issuesOpen) { @($issuesOpen.data.issues).Count } else { 0 }
$closedCount = if ($issuesClosed) { @($issuesClosed.data.issues).Count } else { 0 }

$prsMerged = Invoke-GLCheck "pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "merged", "--limit", "100"
$prMergedData = @()
if ($prsMerged) {
    $pd = $prsMerged.data
    if ($pd.issues) { $prMergedData = @($pd.issues) }
    elseif ($pd.pulls) { $prMergedData = @($pd.pulls) }
    elseif ($pd -is [array]) { $prMergedData = $pd }
}
$prMergedCount = $prMergedData.Count

$membersJson = Invoke-GLCheck "repo", "+members", "--owner", $Owner, "--repo", $Repo, "--limit", "100"
$memberData = @()
if ($membersJson) {
    $md = $membersJson.data
    if ($md.members) { $memberData = @($md.members) }
    elseif ($md -is [array]) { $memberData = $md }
}
$memberCount = $memberData.Count

Log-Ok "Issues(open:$openCount closed:$closedCount) PRs(merged:$prMergedCount) Members:$memberCount"

# -- Step 2: Build Contributor Data --
Log-Step "Building contributor profiles..."

$contribData = @{}

function Ensure-Contrib {
    param([string]$User)
    if (-not $User) { return }
    if (-not $contribData.ContainsKey($User)) {
        $contribData[$User] = @{
            Issues = 0; Merged = 0; Additions = 0; Deletions = 0; Comments = 0; IsMember = $false
        }
    }
}

# Issues
$allIssues = @()
if ($issuesOpen) { $allIssues += @($issuesOpen.data.issues) }
if ($issuesClosed) { $allIssues += @($issuesClosed.data.issues) }
foreach ($issue in $allIssues) {
    $author = if ($issue.author.login) { $issue.author.login } elseif ($issue.author.username) { $issue.author.username } else { $null }
    if ($author) {
        Ensure-Contrib $author
        $contribData[$author].Issues++
    }
}

# Merged PRs + code stats
Log-Step "Analyzing PR code changes (sampling $Sample)..."
$prSample = [Math]::Min($prMergedCount, $Sample)
for ($i = 0; $i -lt $prMergedCount; $i++) {
    $pr = $prMergedData[$i]
    $author = if ($pr.author_login) { $pr.author_login } elseif ($pr.author.login) { $pr.author.login } else { $null }
    $prId = if ($pr.pull_request_number) { $pr.pull_request_number } elseif ($pr.number) { $pr.number } elseif ($pr.id) { $pr.id } else { $null }
    if ($author) {
        Ensure-Contrib $author
        $contribData[$author].Merged++
    }
    if ($i -lt $prSample -and $prId -and $author) {
        $filesJson = Invoke-GLCheck "pr", "+files", "--owner", $Owner, "--repo", $Repo, "--id", $prId
        if ($filesJson -and $filesJson.data.files) {
            foreach ($f in $filesJson.data.files) {
                $add = if ($f.additions) { $f.additions } elseif ($f.addition) { $f.addition } else { 0 }
                $del = if ($f.deletions) { $f.deletions } elseif ($f.deletion) { $f.deletion } else { 0 }
                $contribData[$author].Additions += $add
                $contribData[$author].Deletions += $del
            }
        }
    }
}

# Members
foreach ($m in $memberData) {
    $login = if ($m.login) { $m.login } elseif ($m.username) { $m.username } else { $null }
    if ($login) {
        Ensure-Contrib $login
        $contribData[$login].IsMember = $true
    }
}

# Comments (sample open issues)
Log-Step "Sampling issue comments..."
if ($issuesOpen) {
    $openIssuesArr = @($issuesOpen.data.issues)
    $commentSample = [Math]::Min($openIssuesArr.Count, 10)
    for ($i = 0; $i -lt $commentSample; $i++) {
        $id = $openIssuesArr[$i].id
        if (-not $id) { continue }
        $detailJson = Invoke-GLCheck "issue", "+view", "--owner", $Owner, "--repo", $Repo, "--number", $id
        if ($detailJson) {
            $commentCount = if ($detailJson.data.comment_journals_count) { $detailJson.data.comment_journals_count } else { 0 }
            if ($commentCount -gt 0) {
                $author = $openIssuesArr[$i].author.login
                if ($author) {
                    Ensure-Contrib $author
                    $contribData[$author].Comments += $commentCount
                }
            }
        }
    }
}

# -- Step 3: Calculate Scores --
Log-Step "Calculating scores..."

$maxIssues = 0; $maxMerged = 0; $maxLines = 0; $maxComments = 0
foreach ($user in $contribData.Keys) {
    $c = $contribData[$user]
    if ($c.Issues -gt $maxIssues) { $maxIssues = $c.Issues }
    if ($c.Merged -gt $maxMerged) { $maxMerged = $c.Merged }
    $lines = $c.Additions + $c.Deletions
    if ($lines -gt $maxLines) { $maxLines = $lines }
    if ($c.Comments -gt $maxComments) { $maxComments = $c.Comments }
}

$scores = @{}
foreach ($user in $contribData.Keys) {
    $c = $contribData[$user]
    $ni = if ($maxIssues -gt 0) { $c.Issues / $maxIssues } else { 0 }
    $nm = if ($maxMerged -gt 0) { $c.Merged / $maxMerged } else { 0 }
    $lines = $c.Additions + $c.Deletions
    $nl = if ($maxLines -gt 0) { $lines / $maxLines } else { 0 }
    $nc = if ($maxComments -gt 0) { $c.Comments / $maxComments } else { 0 }
    $ms = if ($c.IsMember) { 1 } else { 0 }
    $score = [Math]::Round($ni * 15 + $nm * 25 + $nl * 30 + $nc * 15 + $ms * 15, 1)
    $scores[$user] = $score
}

# -- Step 4: Display Rankings --
Log-Title "Contributor Rankings"
Write-Host ""
Write-Host ("{0,-4}  {1,-18}  {2,-8}  {3,-8}  {4,-12}  {5,-10}  {6,-8}  {7}" -f "Rank","Contributor","Issues","Merged","+/- Lines","Comments","Score","Badge") -ForegroundColor White
Write-Host "  ----  ------------------  --------  --------  ------------  ----------  --------  -------------"

$ranked = $scores.GetEnumerator() | Sort-Object -Property Value -Descending
$rank = 1
$rankedList = @()
foreach ($entry in $ranked) {
    $user = $entry.Key
    $score = $entry.Value
    $c = $contribData[$user]
    $si = [int]$score
    $badge = if ($si -ge 80) { "Champion" } elseif ($si -ge 60) { "Core Contributor" } elseif ($si -ge 40) { "Active Contributor" } elseif ($si -ge 20) { "Contributor" } else { "Newcomer" }
    $lines = $c.Additions + $c.Deletions
    Write-Host ("{0,-4}  {1,-18}  {2,-8}  {3,-8}  +{4,-6}/-{5,-4}  {6,-10}  {7,-8}  {8}" -f $rank,$user,$c.Issues,$c.Merged,$c.Additions,$c.Deletions,$c.Comments,$score,$badge)
    $rankedList += @{ Rank=$rank; User=$user; Issues=$c.Issues; Merged=$c.Merged; Lines=$lines; Additions=$c.Additions; Deletions=$c.Deletions; Comments=$c.Comments; Score=$score; Badge=$badge }
    $rank++
}

# -- Step 5: Generate HTML Report --
Log-Title "Generating HTML Report"

$pieData = ""
foreach ($entry in $ranked) {
    $pieData += "{value: $($entry.Value), name: '$($entry.Key)'},"
}

$tableRows = ""
foreach ($r in $rankedList) {
    $rankCls = ""
    if ($r.Rank -eq 1) { $rankCls = " rank-1" }
    elseif ($r.Rank -eq 2) { $rankCls = " rank-2" }
    elseif ($r.Rank -eq 3) { $rankCls = " rank-3" }

    $badgeCls = switch ($r.Badge) {
        "Champion" { "champion" }
        "Core Contributor" { "core" }
        "Active Contributor" { "active" }
        "Contributor" { "contributor" }
        default { "newcomer" }
    }

    $tableRows += '                <tr><td class="rank' + $rankCls + '">' + $r.Rank + '</td><td>@' + $r.User + '</td><td>' + $r.Issues + '</td><td>' + $r.Merged + '</td><td>' + $r.Lines + '</td><td>' + $r.Comments + '</td><td>' + $r.Score + '</td><td><span class="badge badge-' + $badgeCls + '">' + $r.Badge + '</span></td></tr>' + "`n"
}

$totalIssuesCount = $openCount + $closedCount
$contribCount = $contribData.Count

$html = '<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contributor Report - ' + $Owner + '/' + $Repo + '</title>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; padding: 40px 20px; }
        .container { max-width: 1200px; margin: 0 auto; }
        .header { text-align: center; color: white; margin-bottom: 40px; }
        .header h1 { font-size: 2.5rem; margin-bottom: 10px; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); }
        .header p { font-size: 1.1rem; opacity: 0.9; }
        .card { background: white; border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); padding: 30px; margin-bottom: 30px; }
        .card h2 { color: #333; margin-bottom: 20px; font-size: 1.5rem; border-bottom: 3px solid #667eea; padding-bottom: 10px; }
        .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
        .stat-card { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; padding: 20px; color: white; text-align: center; }
        .stat-value { font-size: 2rem; font-weight: bold; margin-bottom: 5px; }
        .stat-label { font-size: 0.9rem; opacity: 0.9; }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 12px; text-align: left; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 1px; }
        td { padding: 12px; border-bottom: 1px solid #eee; }
        tr:hover { background: #f8f9ff; }
        .rank { font-weight: bold; color: #667eea; font-size: 1.2rem; }
        .rank-1 { color: #FFD700; }
        .rank-2 { color: #C0C0C0; }
        .rank-3 { color: #CD7F32; }
        .badge { padding: 4px 12px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; }
        .badge-champion { background: #FFD700; color: #333; }
        .badge-core { background: #C0C0C0; color: #333; }
        .badge-active { background: #CD7F32; color: white; }
        .badge-contributor { background: #4CAF50; color: white; }
        .badge-newcomer { background: #9E9E9E; color: white; }
        .chart-container { width: 100%; height: 400px; }
        .weight-info { background: #f8f9ff; border-radius: 12px; padding: 20px; margin-top: 20px; }
        .weight-info h3 { color: #667eea; margin-bottom: 15px; }
        .weight-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; }
        .weight-item { display: flex; justify-content: space-between; padding: 8px 12px; background: white; border-radius: 8px; border-left: 4px solid #667eea; }
        .weight-label { color: #666; }
        .weight-value { font-weight: 600; color: #667eea; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>Contributor Report</h1>
            <p>' + $Owner + '/' + $Repo + ' - Team Contribution Analysis</p>
        </div>
        <div class="stats-grid">
            <div class="stat-card"><div class="stat-value">' + $contribCount + '</div><div class="stat-label">Contributors</div></div>
            <div class="stat-card"><div class="stat-value">' + $totalIssuesCount + '</div><div class="stat-label">Total Issues</div></div>
            <div class="stat-card"><div class="stat-value">' + $prMergedCount + '</div><div class="stat-label">Merged PRs</div></div>
        </div>
        <div class="card">
            <h2>Score Distribution</h2>
            <div id="pieChart" class="chart-container"></div>
        </div>
        <div class="card">
            <h2>Detailed Rankings</h2>
            <table><thead><tr><th>Rank</th><th>Contributor</th><th>Issues</th><th>Merged PRs</th><th>Code Lines</th><th>Comments</th><th>Score</th><th>Badge</th></tr></thead><tbody>
' + $tableRows + '
            </tbody></table>
        </div>
        <div class="card">
            <h2>Scoring System (AHP Weights)</h2>
            <div class="weight-info">
                <div class="weight-grid">
                    <div class="weight-item"><span class="weight-label">Issues Created</span><span class="weight-value">15%</span></div>
                    <div class="weight-item"><span class="weight-label">PRs Merged</span><span class="weight-value">25%</span></div>
                    <div class="weight-item"><span class="weight-label">Code Changes</span><span class="weight-value">30%</span></div>
                    <div class="weight-item"><span class="weight-label">Issue Comments</span><span class="weight-value">15%</span></div>
                    <div class="weight-item"><span class="weight-label">Team Member</span><span class="weight-value">15%</span></div>
                </div>
            </div>
        </div>
    </div>
    <script>
        var chart = echarts.init(document.getElementById("pieChart"));
        chart.setOption({
            tooltip: { trigger: "item", formatter: "{a} <br/>{b}: {c} ({d}%)" },
            legend: { orient: "vertical", left: "left", top: "middle" },
            series: [{
                name: "Score",
                type: "pie",
                radius: ["40%", "70%"],
                center: ["60%", "50%"],
                itemStyle: { borderRadius: 10, borderColor: "#fff", borderWidth: 2 },
                label: { show: true, formatter: "{b}\n{d}%" },
                data: [' + $pieData + ']
            }]
        });
        window.addEventListener("resize", function() { chart.resize(); });
    </script>
</body>
</html>'

$html | Out-File -FilePath $reportFile -Encoding UTF8
Log-Ok "HTML report: $reportFile"

# -- Step 6: Publish to Wiki --
Log-Step "Publishing to Wiki..."

$wikiRankRows = ""
foreach ($r in $rankedList) {
    $shortBadge = switch ($r.Badge) {
        "Champion" { "Champion" }
        "Core Contributor" { "Core" }
        "Active Contributor" { "Active" }
        "Contributor" { "Contributor" }
        default { "Newcomer" }
    }
    $wikiRankRows += "| $($r.Rank) | @$($r.User) | $($r.Issues) | $($r.Merged) | $($r.Lines) | $($r.Comments) | $($r.Score) | $shortBadge |" + "`n"
}

$wikiTitle = "Contributor Leaderboard $(Get-Date -Format 'yyyy-MM-dd')"
$wikiContent = "# Contributor Leaderboard - $Owner/$Repo" + "`n`n"
$wikiContent += "*Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm')*" + "`n`n"
$wikiContent += "## Scoring System" + "`n`n"
$wikiContent += "| Dimension | Weight | Source |" + "`n"
$wikiContent += "|-----------|--------|--------|" + "`n"
$wikiContent += "| Issues Created | 15% | issue +list |" + "`n"
$wikiContent += "| PRs Merged | 25% | pr +list state=merged |" + "`n"
$wikiContent += "| Code Changes | 30% | pr +files |" + "`n"
$wikiContent += "| Issue Comments | 15% | issue +view |" + "`n"
$wikiContent += "| Team Member | 15% | repo +members |" + "`n`n"
$wikiContent += "## Rankings" + "`n`n"
$wikiContent += "| Rank | Contributor | Issues | Merged | Lines | Comments | Score | Badge |" + "`n"
$wikiContent += "|------|-------------|--------|--------|-------|----------|-------|-------|" + "`n"
$wikiContent += $wikiRankRows + "`n"
$wikiContent += "---" + "`n"
$wikiContent += "*Auto-generated by gitlink-cli*"

$wikiResult = Invoke-GL "wiki", "+update", "--owner", $Owner, "--repo", $Repo, "--title", $wikiTitle, "--cover", $wikiContent
if ($wikiResult -and (Get-JsonOk ($wikiResult | ConvertFrom-Json))) {
    Log-Ok "Published to Wiki (updated): $wikiTitle"
} else {
    Log-Info "Update failed (page may not exist), trying create..."
    $wikiResult = Invoke-GL "wiki", "+create", "--owner", $Owner, "--repo", $Repo, "--title", $wikiTitle, "--content", $wikiContent
    if ($wikiResult) {
        try {
            $wikiObj = $wikiResult | ConvertFrom-Json
            if ($wikiObj.ok) {
                Log-Ok "Published to Wiki (created): $wikiTitle"
            } else {
                $wikiErr = if ($wikiObj.error.message) { $wikiObj.error.message } elseif ($wikiObj.message) { $wikiObj.message } else { "unknown error" }
                Log-Warn "Wiki publish failed: $wikiErr"
            }
        } catch {
            Log-Warn "Wiki publish failed: non-JSON response from API"
        }
    } else {
        Log-Warn "Wiki publish failed: no response from API"
    }
}

# -- Step 7: Award Badges (optional) --
if ($Award) {
    Log-Title "Awarding Badges"

    $badgeGroups = @{}
    foreach ($r in $rankedList) {
        if (-not $badgeGroups.ContainsKey($r.Badge)) { $badgeGroups[$r.Badge] = @() }
        $badgeGroups[$r.Badge] += $r.User
    }

    foreach ($badge in $badgeGroups.Keys) {
        $users = $badgeGroups[$badge]
        if ($badge -eq "Newcomer") { continue }

        $userList = ($users | ForEach-Object { "@$_" }) -join ", "
        $issueTitle = "Badge Award: $badge"
        $issueBody = "## Congratulations!" + "`n`n"
        $issueBody += "The following contributors have earned the **$badge** badge:" + "`n`n"
        $issueBody += $userList + "`n`n"
        $issueBody += "### Badge Criteria" + "`n"
        $issueBody += switch ($badge) {
            "Champion" { "- Score >= 80: Exceptional contribution to the project" }
            "Core Contributor" { "- Score >= 60: Significant and consistent contributions" }
            "Active Contributor" { "- Score >= 40: Regular contributions to the project" }
            "Contributor" { "- Score >= 20: Made meaningful contributions" }
        }
        $issueBody += "`n`n---`n*Auto-awarded by gitlink-cli contributor-growth workflow*"

        $issueResult = Invoke-GL "issue", "+create", "--owner", $Owner, "--repo", $Repo, "--title", $issueTitle, "--body", $issueBody
        if ($issueResult) {
            try {
                $issueJson = $issueResult | ConvertFrom-Json
                $issueNum = if ($issueJson.ok -and $issueJson.data.id) { $issueJson.data.id } elseif ($issueJson.ok -and $issueJson.data.number) { $issueJson.data.number } else { $null }
                if ($issueNum) {
                    Invoke-GL "issue", "+label-add", "--owner", $Owner, "--repo", $Repo, "--number", $issueNum, "--labels", "badge" | Out-Null
                    Log-Ok "Badge issue created: #$issueNum - $issueTitle ($($users.Count) recipients)"
                }
            } catch {
                Log-Warn "Badge issue creation may have failed: $issueTitle"
            }
        }
    }
}

# ----------------------------------------------------------------
Log-Title "Complete"
# ----------------------------------------------------------------

Write-Host "  Contributors: $contribCount" -ForegroundColor Green
Write-Host "  HTML Report:  $reportFile" -ForegroundColor Green
Write-Host "  Wiki:         $wikiTitle" -ForegroundColor Green
if ($Award) { Write-Host "  Badges:       Awarded" -ForegroundColor Green }
