package webhooks

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	"source.offmarket.win/aleagle/eaglecast/models"
)

type BounceDetails struct {
	Action   string `json:"action"`
	Message  string `json:"message"`
	Category string `json:"category"`
	Code     int    `json:"code"`
	Status   any    `json:"status"`
	Line     int    `json:"line"`
}

type forwardemailNotif struct {
	EmailID         string            `json:"email_id"`
	ListID          string            `json:"list_id"`
	ListUnsubscribe string            `json:"list_unsubscribe"`
	FeedbackID      string            `json:"feedback_id"`
	Recipient       string            `json:"recipient"`
	Message         string            `json:"message"`
	Response        string            `json:"response"`
	ResponseCode    int               `json:"response_code"`
	TruthSource     string            `json:"truth_source"`
	Headers         map[string]string `json:"headers"`
	Bounce          BounceDetails     `json:"bounce"`
	BouncedAt       time.Time         `json:"bounced_at"`
}

// Forwardemail handles webhook notifications (mainly bounce notifications).
type Forwardemail struct {
	hmacKey []byte
}

func NewForwardemail(key []byte) *Forwardemail {
	return &Forwardemail{hmacKey: key}
}

func (p *Forwardemail) ProcessBounce(sigHex string, body []byte) ([]models.Bounce, error) {
	if len(p.hmacKey) == 0 {
		return nil, errors.New("webhook key is not configured")
	}

	// Decode the hex-encoded signature from the webhook
	sig, err := hex.DecodeString(sigHex)
	if err != nil {
		return nil, fmt.Errorf("invalid signature encoding: %v", err)
	}

	// Generate HMAC using the request body and secret key
	mac := hmac.New(sha256.New, p.hmacKey)
	mac.Write(body)
	expectedSignature := mac.Sum(nil)

	// Compare the generated signature with the provided signature
	if !hmac.Equal(expectedSignature, sig) {
		return nil, errors.New("invalid signature")
	}

	// Parse the JSON payload
	var n forwardemailNotif
	if err := json.Unmarshal(body, &n); err != nil {
		return nil, fmt.Errorf("error unmarshalling Forwardemail notification: %v", err)
	}

	// Categorize the bounce type
	typ := models.BounceTypeSoft
	hardBounceCategories := []string{"block", "recipient", "virus", "spam"}
	for _, category := range hardBounceCategories {
		if n.Bounce.Category == category {
			typ = models.BounceTypeHard
			break
		}
	}

	campUUID := ""
	if v, ok := n.Headers["X-EagleCast-Campaign"]; ok {
		campUUID = v
	}

	return []models.Bounce{{
		Email:        strings.ToLower(n.Recipient),
		CampaignUUID: campUUID,
		Type:         typ,
		Source:       "forwardemail",
		Meta:         json.RawMessage(body),
		CreatedAt:    n.BouncedAt,
	}}, nil
}
