package ui

import (
	"fmt"
	"strings"

	packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1"
	"github.com/safedep/pmg/proxy"
)

// ecosystemLabel maps the ecosystem enum to the label users know the
// registry by (npm, pypi, go, ...) instead of the raw enum name.
func ecosystemLabel(ecosystem packagev1.Ecosystem) string {
	return strings.ToLower(strings.TrimPrefix(ecosystem.String(), "ECOSYSTEM_"))
}

// ProxyPresenter composes all user-facing text authored by the proxy layer.
// Interceptors return structured decisions; any new proxy-emitted message
// belongs here, not in the proxy layer.
type ProxyPresenter struct {
	// Advisory returns the org-configured advisory message appended to
	// policy block messages. Read at render time so config changes apply
	// to subsequent blocks. nil means no advisory.
	Advisory func() string
}

// BlockMessage renders the response body for a blocked proxy request
// from the interceptor's structured block decision.
func (p ProxyPresenter) BlockMessage(reason proxy.BlockReason, blockCtx *proxy.BlockContext) string {
	if blockCtx == nil {
		return ""
	}

	ecosystem := ecosystemLabel(blockCtx.Ecosystem)

	var message string
	switch reason {
	case proxy.BlockReasonMalware, proxy.BlockReasonUserDeclined:
		prefix := "Malicious package blocked"
		if reason == proxy.BlockReasonUserDeclined {
			prefix = "Installation blocked by user"
		}

		message = fmt.Sprintf("%s: %s/%s@%s\n\nReason: %s",
			prefix, ecosystem, blockCtx.PackageName, blockCtx.PackageVersion, blockCtx.MalwareSummary)
		if blockCtx.MalwareReferenceURL != "" {
			message += "\n\nReference: " + blockCtx.MalwareReferenceURL
		}

	case proxy.BlockReasonConfirmationFailed:
		// Operational failure rather than a policy decision; the advisory
		// message is intentionally not appended.
		return fmt.Sprintf("Failed to get user confirmation for suspicious package %s/%s@%s",
			ecosystem, blockCtx.PackageName, blockCtx.PackageVersion)

	case proxy.BlockReasonDependencyCooldown:
		message = fmt.Sprintf("Package blocked by dependency cooldown: %s/%s@%s\n\nPublished %d day(s) ago; cooldown window is %d day(s) (%d remaining).",
			ecosystem, blockCtx.PackageName, blockCtx.PackageVersion,
			blockCtx.CooldownDaysAgo, blockCtx.CooldownDays, blockCtx.CooldownDaysLeft)

	default:
		return ""
	}

	if p.Advisory != nil {
		if advisory := p.Advisory(); advisory != "" {
			message += "\n\n" + advisory
		}
	}
	return message
}
