package contrib

import (
	"fmt"
	"net/url"

	"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)

// Contributor 贡献者信息
type Contributor struct {
	Login     string
	Name      string
	Commits   int
	Additions int
	Deletions int
	Issues    int
	PRs       int
	Score     float64
}

// AHP 权重（基于层次分析法计算）
const (
	WeightCommits   = 0.143
	WeightCodeLines = 0.286
	WeightPRs       = 0.071
	WeightIssues    = 0.05
	WeightIssueSolve = 0.1
	WeightRelease   = 0.1
	WeightComments  = 0.083
	WeightPRReview  = 0.083
	WeightWiki      = 0.083
)

// fetchContributors 从 issue 和 PR 数据中提取贡献者
func fetchContributors(ctx *common.RuntimeContext) ([]Contributor, error) {
	contributorMap := make(map[string]*Contributor)

	// 1. 从 Issue 列表中提取贡献者
	issues, err := fetchAllIssues(ctx)
	if err != nil {
		return nil, fmt.Errorf("fetch issues: %w", err)
	}
	for _, issue := range issues {
		login := issue["login"]
		name := issue["name"]
		if login == "" {
			continue
		}
		if _, exists := contributorMap[login]; !exists {
			contributorMap[login] = &Contributor{
				Login: login,
				Name:  name,
			}
			if contributorMap[login].Name == "" {
				contributorMap[login].Name = login
			}
		}
		contributorMap[login].Issues++
	}

	// 2. 从 PR 列表中提取贡献者
	prs, err := fetchAllPRs(ctx)
	if err != nil {
		return nil, fmt.Errorf("fetch PRs: %w", err)
	}
	for _, pr := range prs {
		login := pr["login"]
		name := pr["name"]
		if login == "" {
			continue
		}
		if _, exists := contributorMap[login]; !exists {
			contributorMap[login] = &Contributor{
				Login: login,
				Name:  name,
			}
			if contributorMap[login].Name == "" {
				contributorMap[login].Name = login
			}
		}
		contributorMap[login].PRs++
	}

	// 转换为切片
	var contributors []Contributor
	for _, c := range contributorMap {
		contributors = append(contributors, *c)
	}

	if len(contributors) == 0 {
		return nil, fmt.Errorf("no contributors found")
	}

	return contributors, nil
}

// fetchAllIssues 获取所有 Issue
func fetchAllIssues(ctx *common.RuntimeContext) ([]map[string]string, error) {
	var results []map[string]string
	page := 1

	for {
		q := url.Values{}
		q.Set("page", fmt.Sprintf("%d", page))
		q.Set("limit", "100")
		q.Set("state", "all")

		env, err := ctx.CallAPIWithQuery("GET", fmt.Sprintf("/v1/%s/%s/issues", ctx.Owner, ctx.Repo), q)
		if err != nil {
			return nil, err
		}

		data, ok := env.Data.(map[string]interface{})
		if !ok {
			break
		}

		issues, ok := data["issues"].([]interface{})
		if !ok || len(issues) == 0 {
			break
		}

		for _, item := range issues {
			issue, ok := item.(map[string]interface{})
			if !ok {
				continue
			}
			author, ok := issue["author"].(map[string]interface{})
			if !ok {
				continue
			}
			login := getString(author, "login")
			name := getString(author, "name")
			if login != "" {
				results = append(results, map[string]string{
					"login": login,
					"name":  name,
				})
			}
		}

		totalCount := getInt(data, "total_count")
		if page*100 >= totalCount {
			break
		}
		page++
	}

	return results, nil
}

// fetchAllPRs 获取所有 PR
func fetchAllPRs(ctx *common.RuntimeContext) ([]map[string]string, error) {
	var results []map[string]string
	page := 1

	for {
		q := url.Values{}
		q.Set("page", fmt.Sprintf("%d", page))
		q.Set("limit", "100")
		q.Set("state", "all")

		env, err := ctx.CallAPIWithQuery("GET", fmt.Sprintf("/v1/%s/%s/pulls", ctx.Owner, ctx.Repo), q)
		if err != nil {
			return nil, err
		}

		data, ok := env.Data.(map[string]interface{})
		if !ok {
			break
		}

		// PR 列表字段是 "pulls"
		prs, ok := data["pulls"].([]interface{})
		if !ok || len(prs) == 0 {
			break
		}

		for _, item := range prs {
			pr, ok := item.(map[string]interface{})
			if !ok {
				continue
			}
			// PR 的作者信息在 issue.author 中
			login := ""
			name := ""
			if issue, ok := pr["issue"].(map[string]interface{}); ok {
				if author, ok := issue["author"].(map[string]interface{}); ok {
					login = getString(author, "login")
					name = getString(author, "name")
				}
			}
			if login != "" {
				results = append(results, map[string]string{
					"login": login,
					"name":  name,
				})
			}
		}

		// 检查是否还有更多页
		searchCount := getInt(data, "search_count")
		if page*100 >= searchCount {
			break
		}
		page++
	}

	return results, nil
}

// calculateScores 计算加权贡献分数
func calculateScores(contributors []Contributor, issueCounts, prCounts map[string]int) []Contributor {
	// 如果提供了额外的计数，更新贡献者数据
	if issueCounts != nil {
		for i := range contributors {
			c := &contributors[i]
			if count, ok := issueCounts[c.Login]; ok {
				c.Issues = count
			}
		}
	}
	if prCounts != nil {
		for i := range contributors {
			c := &contributors[i]
			if count, ok := prCounts[c.Login]; ok {
				c.PRs = count
			}
		}
	}

	// 找到各指标的最大值（用于归一化）
	maxIssues := 0
	maxPRs := 0

	for i := range contributors {
		c := &contributors[i]
		if c.Issues > maxIssues {
			maxIssues = c.Issues
		}
		if c.PRs > maxPRs {
			maxPRs = c.PRs
		}
	}

	// 计算加权分数（归一化后）
	for i := range contributors {
		c := &contributors[i]

		// 归一化到 0-1
		normIssues := 0.0
		normPRs := 0.0

		if maxIssues > 0 {
			normIssues = float64(c.Issues) / float64(maxIssues)
		}
		if maxPRs > 0 {
			normPRs = float64(c.PRs) / float64(maxPRs)
		}

		// 加权求和（只用 issue 和 PR，因为 commits API 不可用）
		c.Score = normIssues*WeightIssues + normPRs*WeightPRs
	}

	return contributors
}

// getString 从 map 中获取字符串
func getString(m map[string]interface{}, key string) string {
	if v, ok := m[key]; ok {
		if s, ok := v.(string); ok {
			return s
		}
	}
	return ""
}

// getInt 从 map 中获取整数
func getInt(m map[string]interface{}, key string) int {
	if v, ok := m[key]; ok {
		switch n := v.(type) {
		case float64:
			return int(n)
		case int:
			return n
		}
	}
	return 0
}
