package mail

import (
	"strconv"
	"strings"

	"github.com/ultisuite/ulti-backend/internal/api/apivalidate"
)

const (
	maxIdentityRequestBody = 256 << 10 // 256 KiB
	maxIdentityName        = 128
	maxSignatureHTML       = 64 << 10 // 64 KiB
	maxReplyToAddrs        = 10
)

type createIdentityRequest struct {
	Email               string   `json:"email"`
	Name                string   `json:"name"`
	IsDefault           bool     `json:"is_default"`
	SignatureHTML       string   `json:"signature_html"`
	DefaultSignatureID  string   `json:"default_signature_id"`
	ReplyToAddrs        []string `json:"reply_to_addrs"`
}

type updateIdentityRequest struct {
	Email               string   `json:"email"`
	Name                string   `json:"name"`
	IsDefault           bool     `json:"is_default"`
	SignatureHTML       string   `json:"signature_html"`
	DefaultSignatureID  string   `json:"default_signature_id"`
	ReplyToAddrs        []string `json:"reply_to_addrs"`
}

func validateReplyToAddrs(field string, addrs []string) []apivalidate.FieldDetail {
	if len(addrs) > maxReplyToAddrs {
		return []apivalidate.FieldDetail{{
			Field: field, Message: "too many entries",
		}}
	}
	var details []apivalidate.FieldDetail
	for i, addr := range addrs {
		if d := validateRecipient(addr); d != nil {
			d.Field = field + "[" + strconv.Itoa(i) + "]"
			details = append(details, *d)
		}
	}
	return details
}

func validateCreateIdentity(req *createIdentityRequest) *apivalidate.ValidationError {
	var details []apivalidate.FieldDetail
	if d := validateEmailField("email", req.Email); d != nil {
		details = append(details, *d)
	}
	if req.Name != "" && len(req.Name) > maxIdentityName {
		details = append(details, apivalidate.FieldDetail{Field: "name", Message: "too long"})
	}
	if len(req.SignatureHTML) > maxSignatureHTML {
		details = append(details, apivalidate.FieldDetail{Field: "signature_html", Message: "too long"})
	}
	if d := validateOptionalUUID("default_signature_id", req.DefaultSignatureID); d != nil {
		details = append(details, *d)
	}
	if req.ReplyToAddrs == nil {
		req.ReplyToAddrs = []string{}
	}
	details = append(details, validateReplyToAddrs("reply_to_addrs", req.ReplyToAddrs)...)
	if len(details) == 0 {
		return nil
	}
	return apivalidate.NewValidationError(details...)
}

func validateUpdateIdentity(req *updateIdentityRequest) *apivalidate.ValidationError {
	var details []apivalidate.FieldDetail
	if d := validateEmailField("email", req.Email); d != nil {
		details = append(details, *d)
	}
	if strings.TrimSpace(req.Name) == "" {
		details = append(details, apivalidate.FieldDetail{Field: "name", Message: "required"})
	} else if len(req.Name) > maxIdentityName {
		details = append(details, apivalidate.FieldDetail{Field: "name", Message: "too long"})
	}
	if len(req.SignatureHTML) > maxSignatureHTML {
		details = append(details, apivalidate.FieldDetail{Field: "signature_html", Message: "too long"})
	}
	if d := validateOptionalUUID("default_signature_id", req.DefaultSignatureID); d != nil {
		details = append(details, *d)
	}
	if req.ReplyToAddrs == nil {
		req.ReplyToAddrs = []string{}
	}
	details = append(details, validateReplyToAddrs("reply_to_addrs", req.ReplyToAddrs)...)
	if len(details) == 0 {
		return nil
	}
	return apivalidate.NewValidationError(details...)
}

func validateOptionalUUID(field, value string) *apivalidate.FieldDetail {
	if value == "" {
		return nil
	}
	return validateAccountUUID(value)
}
