package idem

import (
	"crypto/sha256"
	"encoding/hex"
	"strings"
	"time"

	"github.com/tech/sendico/pkg/merrors"
	"go.uber.org/zap"
)

const hashSep = "\x1f"

func (s *svc) Fingerprint(in FPInput) (fingerprint string, err error) {
	logger := s.logger
	logger.Debug("Starting Fingerprint",
		zap.String("organization_ref", strings.ToLower(strings.TrimSpace(in.OrganizationRef))),
		zap.String("quotation_ref", strings.TrimSpace(in.QuotationRef)),
		zap.String("intent_ref", strings.TrimSpace(in.IntentRef)),
		zap.Bool("has_client_payment_ref", strings.TrimSpace(in.ClientPaymentRef) != ""),
	)
	defer func(start time.Time) {
		fields := []zap.Field{zap.Int64("duration_ms", time.Since(start).Milliseconds())}
		if err != nil {
			logger.Warn("Failed to fingerprint", append(fields, zap.Error(err))...)
			return
		}
		logger.Debug("Completed Fingerprint", append(fields, zap.Bool("generated", strings.TrimSpace(fingerprint) != ""))...)
	}(time.Now())

	orgRef := strings.ToLower(strings.TrimSpace(in.OrganizationRef))
	if orgRef == "" {
		return "", merrors.InvalidArgument("organization_ref is required")
	}
	quotationRef := strings.TrimSpace(in.QuotationRef)
	if quotationRef == "" {
		return "", merrors.InvalidArgument("quotation_ref is required")
	}
	intentRef := strings.TrimSpace(in.IntentRef)
	clientPaymentRef := strings.TrimSpace(in.ClientPaymentRef)

	payload := strings.Join([]string{
		"org=" + orgRef,
		"quote=" + quotationRef,
		"intent=" + intentRef,
		"client=" + clientPaymentRef,
	}, hashSep)

	fingerprint = hashBytes([]byte(payload))
	return fingerprint, nil
}

func hashBytes(data []byte) string {
	sum := sha256.Sum256(data)
	return hex.EncodeToString(sum[:])
}
