// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package git

import (
	"context"
	"strings"

	"gitea.dev/modules/git/gitcmd"
	"gitea.dev/modules/setting"
)

// Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat
const (
	SigningKeyFormatOpenPGP = "openpgp" // for GPG keys, the expected default of git cli
	SigningKeyFormatSSH     = "ssh"
)

// SigningKey represents an instance key info which will be used to sign git commits.
// FIXME: need to refactor it to a new name, this name conflicts with the variable names for "asymkey.GPGKey" in many places.
type SigningKey struct {
	KeyID  string
	Format string
}

func (s *SigningKey) String() string {
	// Do not expose KeyID
	// In case the key is a file path and the struct is rendered in a template, then the server path will be exposed.
	setting.PanicInDevOrTesting("don't call SigningKey.String() - it exposes the KeyID which might be a local file path")
	return "SigningKey:" + s.Format
}

// GetSigningKey returns the KeyID and git Signature for the repo
func GetSigningKey(ctx context.Context) (*SigningKey, *Signature) {
	if setting.Repository.Signing.SigningKey == "none" {
		return nil, nil
	}

	if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" {
		// Can ignore the error here as it means that commit.gpgsign is not set
		value, _, _ := gitcmd.NewCommand("config", "--global", "--get", "commit.gpgsign").RunStdString(ctx)
		sign, valid := ParseBool(strings.TrimSpace(value))
		if !sign || !valid {
			return nil, nil
		}

		format, _, _ := gitcmd.NewCommand("config", "--global", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx)
		signingKey, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.signingkey").RunStdString(ctx)
		signingName, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.name").RunStdString(ctx)
		signingEmail, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.email").RunStdString(ctx)

		if strings.TrimSpace(signingKey) == "" {
			return nil, nil
		}

		return &SigningKey{
				KeyID:  strings.TrimSpace(signingKey),
				Format: strings.TrimSpace(format),
			}, &Signature{
				Name:  strings.TrimSpace(signingName),
				Email: strings.TrimSpace(signingEmail),
			}
	}

	if setting.Repository.Signing.SigningKey == "" {
		return nil, nil
	}

	return &SigningKey{
			KeyID:  setting.Repository.Signing.SigningKey,
			Format: setting.Repository.Signing.SigningFormat,
		}, &Signature{
			Name:  setting.Repository.Signing.SigningName,
			Email: setting.Repository.Signing.SigningEmail,
		}
}
