package mail

import (
	"encoding/json"
	"strconv"
	"strings"

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

type draftRequest struct {
	AccountID   string   `json:"account_id"`
	IdentityID  string   `json:"identity_id"`
	To          []string `json:"to"`
	Cc          []string `json:"cc"`
	Bcc         []string `json:"bcc"`
	Subject     string   `json:"subject"`
	BodyText    string   `json:"body_text"`
	BodyHTML    string   `json:"body_html"`
	InReplyTo   string   `json:"in_reply_to"`
	Attachments any      `json:"attachments"`
}

func validateDraftRecipients(req *draftRequest) []apivalidate.FieldDetail {
	var details []apivalidate.FieldDetail
	for i, addr := range req.To {
		if d := validateRecipient(addr); d != nil {
			d.Field = "to[" + strconv.Itoa(i) + "]"
			details = append(details, *d)
		}
	}
	for i, addr := range req.Cc {
		if d := validateRecipient(addr); d != nil {
			d.Field = "cc[" + strconv.Itoa(i) + "]"
			details = append(details, *d)
		}
	}
	for i, addr := range req.Bcc {
		if d := validateRecipient(addr); d != nil {
			d.Field = "bcc[" + strconv.Itoa(i) + "]"
			details = append(details, *d)
		}
	}
	return details
}

func validateDraftContent(req *draftRequest) []apivalidate.FieldDetail {
	var details []apivalidate.FieldDetail
	if len(req.Subject) > maxSubjectLen {
		details = append(details, apivalidate.FieldDetail{Field: "subject", Message: "too long"})
	}
	if len(req.BodyText) > limits.MaxBodyFieldBytes {
		details = append(details, apivalidate.FieldDetail{Field: "body_text", Message: "too long"})
	}
	if len(req.BodyHTML) > limits.MaxBodyFieldBytes {
		details = append(details, apivalidate.FieldDetail{Field: "body_html", Message: "too long"})
	}
	if req.InReplyTo != "" && len(req.InReplyTo) > 998 {
		details = append(details, apivalidate.FieldDetail{Field: "in_reply_to", Message: "too long"})
	}
	if req.Attachments != nil {
		if b, err := json.Marshal(req.Attachments); err != nil {
			details = append(details, apivalidate.FieldDetail{Field: "attachments", Message: "invalid"})
		} else if len(b) > limits.MaxSendRequestBodyBytes {
			details = append(details, apivalidate.FieldDetail{Field: "attachments", Message: "too large"})
		}
	}
	return details
}

func validateCreateDraft(req *draftRequest) *apivalidate.ValidationError {
	var details []apivalidate.FieldDetail
	if strings.TrimSpace(req.AccountID) == "" {
		details = append(details, apivalidate.FieldDetail{Field: "account_id", Message: "required"})
	}
	details = append(details, validateDraftRecipients(req)...)
	details = append(details, validateDraftContent(req)...)
	if len(details) == 0 {
		return nil
	}
	return apivalidate.NewValidationError(details...)
}

func validateUpdateDraft(req *draftRequest) *apivalidate.ValidationError {
	var details []apivalidate.FieldDetail
	details = append(details, validateDraftRecipients(req)...)
	details = append(details, validateDraftContent(req)...)
	if len(details) == 0 {
		return nil
	}
	return apivalidate.NewValidationError(details...)
}
