package app

import (
	"context"
	"net/http"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/core/webhook"
	"github.com/tidbcloud/AgentTeam/internal/store/app/webhooks"
)

type giteaPullRequestResource struct {
	providerPullRequestResource
	RepositoryFullName string
	Number             int
}

func (store *Store) loadVerifiedGiteaWebhookConnection(ctx context.Context, app webhooks.AppDefinition, headers http.Header, payload []byte) (webhookAppConnection, bool, error) {
	repositoryRef, organizationRef, parsedForRouting := extractGiteaConnectionRefs(payload)
	if !parsedForRouting {
		return webhookAppConnection{}, false, nil
	}
	candidates := make([]string, 0, 2)
	if repositoryRef != "" {
		candidates = append(candidates, repositoryRef)
	}
	if organizationRef != "" && !strings.EqualFold(organizationRef, repositoryRef) {
		candidates = append(candidates, organizationRef)
	}

	sawCandidate := false
	for _, externalSubjectRef := range candidates {
		matches, err := store.loadEnabledConnectionsByExternalRef(ctx, app.AppID, externalSubjectRef)
		if err != nil {
			return webhookAppConnection{}, false, err
		}
		if len(matches) == 0 {
			continue
		}
		sawCandidate = true
		for _, connection := range matches {
			webhookSecret, err := extractWebhookSecret(connection.Credentials)
			if err != nil {
				return webhookAppConnection{}, false, err
			}
			if verifyGiteaWebhookSignature(headers.Get("X-Gitea-Signature"), payload, webhookSecret) {
				return connection, true, nil
			}
		}
	}
	if sawCandidate {
		return webhookAppConnection{}, false, ErrUnauthorized
	}
	return webhookAppConnection{}, false, nil
}

func extractGiteaConnectionRefs(payload []byte) (string, string, bool) {
	return webhook.ExtractGiteaConnectionRefs(payload)
}

func verifyGiteaWebhookSignature(signatureHeader string, payload []byte, secret string) bool {
	return webhook.VerifyGiteaWebhookSignature(signatureHeader, payload, secret)
}

func giteaWebhookDeliveryKey(deliveryHeader string, eventType string, payload []byte) string {
	return webhook.GiteaWebhookDeliveryKey(deliveryHeader, eventType, payload)
}

func parseGiteaWebhookPayload(payload []byte) (webhook.GiteaPayload, bool, error) {
	return webhook.ParseGiteaWebhookPayload(payload)
}

func normalizeGiteaWebhookEventType(eventHeader string, action string) string {
	return webhook.NormalizeGiteaWebhookEventType(eventHeader, action)
}

func giteaPullRequestResourceFromPullRequest(event webhook.GiteaPayload, instanceURL string) (giteaPullRequestResource, bool) {
	resource, ok := webhook.GiteaPullRequestResourceFromPullRequest(event, instanceURL)
	return giteaPullRequestResourceFromService(resource), ok
}

func giteaPullRequestResourceFromIssueComment(event webhook.GiteaPayload, instanceURL string) (giteaPullRequestResource, bool, bool) {
	resource, ok, isPullRequestComment := webhook.GiteaPullRequestResourceFromIssueComment(event, instanceURL)
	return giteaPullRequestResourceFromService(resource), ok, isPullRequestComment
}

func giteaPullRequestResourceFromNumber(repositoryFullName string, number int64, resourceURL string, instanceURL string) (giteaPullRequestResource, bool) {
	resource, ok := webhook.GiteaPullRequestResourceFromNumber(repositoryFullName, number, resourceURL, instanceURL)
	return giteaPullRequestResourceFromService(resource), ok
}

func giteaPullRequestResourceFromService(resource webhook.PullRequestResource) giteaPullRequestResource {
	return giteaPullRequestResource{
		providerPullRequestResource: providerPullRequestResource{
			ResourceType:       resource.ResourceType,
			ResourceIdentifier: resource.ResourceIdentifier,
			ResourceURL:        resource.ResourceURL,
		},
		RepositoryFullName: resource.RepositoryFullName,
		Number:             resource.Number,
	}
}

func buildGiteaPullRequestURL(instanceURL string, repositoryFullName string, number int) string {
	return webhook.BuildGiteaPullRequestURL(instanceURL, repositoryFullName, number)
}

func splitPathSegments(path string) []string {
	return webhook.SplitPathSegments(path)
}

func normalizeGiteaReviewState(value string) string {
	return webhook.NormalizeGiteaReviewState(value)
}
