// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
// SPDX-License-Identifier: GPL-3.0-or-later

package badge

import (
	"context"
	"fmt"
	"strings"

	"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
	git_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/git"
	repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
)

// Preset colors for repo badges
const (
	ColorGreen  = "#4c1"
	ColorYellow = "#dfb317"
	ColorRed    = "#e05d44"
	ColorGrey   = "#9f9f9f"
	ColorBlue   = "#007ec6"
)

// GenerateRepoBadge creates a badge for the given repo and badge type.
func GenerateRepoBadge(ctx context.Context, repo *repo_model.Repository, badgeType string) Badge {
	switch strings.ToLower(badgeType) {
	case "version":
		return versionBadge(ctx, repo)
	case "build":
		return buildBadge(ctx, repo)
	case "license":
		return licenseBadge(ctx, repo)
	case "health":
		return healthBadge(ctx, repo)
	default:
		return GenerateBadge("badge", "unknown", ColorGrey)
	}
}

func versionBadge(ctx context.Context, repo *repo_model.Repository) Badge {
	release, err := repo_model.GetLatestReleaseByRepoID(ctx, repo.ID)
	if err != nil || release == nil {
		return GenerateBadge("version", "none", ColorGrey)
	}
	return GenerateBadge("version", release.TagName, ColorBlue)
}

func buildBadge(ctx context.Context, repo *repo_model.Repository) Badge {
	status, err := git_model.GetLatestCommitStatus(ctx, repo.ID, repo.DefaultBranch, db.ListOptions{PageSize: 1})
	if err != nil || len(status) == 0 {
		return GenerateBadge("build", "unknown", ColorGrey)
	}

	switch status[0].State.String() {
	case "success":
		return GenerateBadge("build", "passing", ColorGreen)
	case "failure", "error":
		return GenerateBadge("build", "failing", ColorRed)
	case "pending":
		return GenerateBadge("build", "pending", ColorYellow)
	default:
		return GenerateBadge("build", status[0].State.String(), ColorGrey)
	}
}

func licenseBadge(ctx context.Context, repo *repo_model.Repository) Badge {
	licenses, err := repo_model.GetRepoLicenses(ctx, repo)
	if err != nil || len(licenses) == 0 {
		return GenerateBadge("license", "none", ColorGrey)
	}
	return GenerateBadge("license", licenses.StringList()[0], ColorBlue)
}

func healthBadge(ctx context.Context, repo *repo_model.Repository) Badge {
	score := 0
	licenses, _ := repo_model.GetRepoLicenses(ctx, repo)
	if len(licenses) > 0 {
		score++
	}
	if repo.Description != "" {
		score++
	}
	if len(repo.Topics) > 0 {
		score++
	}

	switch {
	case score >= 3:
		return GenerateBadge("health", "healthy", ColorGreen)
	case score >= 2:
		return GenerateBadge("health", "fair", ColorYellow)
	default:
		return GenerateBadge("health", "needs work", ColorRed)
	}
}

// FormatRepoBadgeSVG returns the badge as SVG HTML for the given repo badge type.
func FormatRepoBadgeSVG(ctx context.Context, repo *repo_model.Repository, badgeType, style string) (string, error) {
	b := GenerateRepoBadge(ctx, repo, badgeType)
	switch style {
	case "flat-square":
		return b.RenderFlatSquare(), nil
	default:
		return b.RenderFlat(), nil
	}
}

// RenderFlat returns the badge as flat-style SVG.
func (b Badge) RenderFlat() string {
	return fmt.Sprintf(`<svg xmlns="http://www.w3.org/2000/svg" width="%d" height="20">
<rect width="%d" height="20" fill="#555"/><rect x="%d" width="%d" height="20" fill="%s"/>
<g fill="#fff" text-anchor="middle" font-family="Verdana,sans-serif" font-size="11">
<text x="%d" y="14">%s</text><text x="%d" y="14">%s</text>
</g></svg>`,
		b.Label.Width()+b.Message.Width(), b.Label.Width(), b.Label.Width(), b.Message.Width(), b.Color,
		b.Label.X(), b.Label.Text(), b.Message.X(), b.Message.Text())
}

// RenderFlatSquare returns the badge as flat-square-style SVG.
func (b Badge) RenderFlatSquare() string {
	return b.RenderFlat() // same for now
}
