package mail

import (
	"strings"

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

const (
	maxFoldersRequestBody = 32 << 10 // 32 KiB
	maxLabelsRequestBody  = 8 << 10  // 8 KiB
	maxFolderName         = 256
	maxRemoteName         = 512
	maxLabelName          = 128
	maxLabelColor         = 32
)

var allowedFolderTypes = map[string]struct{}{
	"inbox":   {},
	"sent":    {},
	"drafts":  {},
	"trash":   {},
	"archive": {},
	"spam":    {},
	"custom":  {},
}

type createFolderRequest struct {
	AccountID  string `json:"account_id"`
	Name       string `json:"name"`
	RemoteName string `json:"remote_name"`
	FolderType string `json:"folder_type"`
}

type updateFolderRequest struct {
	Name       string `json:"name"`
	RemoteName string `json:"remote_name"`
	FolderType string `json:"folder_type"`
}

type createUserLabelRequest struct {
	Name  string `json:"name"`
	Color string `json:"color"`
}

type updateUserLabelRequest struct {
	Name  string `json:"name"`
	Color string `json:"color"`
}

func validateFolderType(field, folderType string) *apivalidate.FieldDetail {
	folderType = strings.TrimSpace(strings.ToLower(folderType))
	if folderType == "" {
		return nil
	}
	if _, ok := allowedFolderTypes[folderType]; !ok {
		return &apivalidate.FieldDetail{Field: field, Message: "invalid"}
	}
	return nil
}

func normalizeFolderType(folderType string) string {
	folderType = strings.TrimSpace(strings.ToLower(folderType))
	if folderType == "" {
		return "custom"
	}
	return folderType
}

func validateFolderName(field, name string, required bool) *apivalidate.FieldDetail {
	name = strings.TrimSpace(name)
	if name == "" {
		if required {
			return &apivalidate.FieldDetail{Field: field, Message: "required"}
		}
		return nil
	}
	if len(name) > maxFolderName || containsNewline(name) {
		return &apivalidate.FieldDetail{Field: field, Message: "invalid"}
	}
	return nil
}

func validateRemoteName(field, remoteName string, required bool) *apivalidate.FieldDetail {
	remoteName = strings.TrimSpace(remoteName)
	if remoteName == "" {
		if required {
			return &apivalidate.FieldDetail{Field: field, Message: "required"}
		}
		return nil
	}
	if len(remoteName) > maxRemoteName || containsNewline(remoteName) {
		return &apivalidate.FieldDetail{Field: field, Message: "invalid"}
	}
	return nil
}

func validateCreateFolder(req *createFolderRequest) *apivalidate.ValidationError {
	var details []apivalidate.FieldDetail
	if strings.TrimSpace(req.AccountID) == "" {
		details = append(details, apivalidate.FieldDetail{Field: "account_id", Message: "required"})
	}
	if d := validateFolderName("name", req.Name, true); d != nil {
		details = append(details, *d)
	}
	if d := validateRemoteName("remote_name", req.RemoteName, false); d != nil {
		details = append(details, *d)
	}
	if d := validateFolderType("folder_type", req.FolderType); d != nil {
		details = append(details, *d)
	}
	if len(details) == 0 {
		return nil
	}
	return apivalidate.NewValidationError(details...)
}

func validateUpdateFolder(req *updateFolderRequest) *apivalidate.ValidationError {
	var details []apivalidate.FieldDetail
	if d := validateFolderName("name", req.Name, true); d != nil {
		details = append(details, *d)
	}
	if d := validateRemoteName("remote_name", req.RemoteName, true); d != nil {
		details = append(details, *d)
	}
	if d := validateFolderType("folder_type", req.FolderType); d != nil {
		details = append(details, *d)
	}
	if len(details) == 0 {
		return nil
	}
	return apivalidate.NewValidationError(details...)
}

func validateLabelName(field, name string, required bool) *apivalidate.FieldDetail {
	name = strings.TrimSpace(name)
	if name == "" {
		if required {
			return &apivalidate.FieldDetail{Field: field, Message: "required"}
		}
		return nil
	}
	if len(name) > maxLabelName || containsNewline(name) {
		return &apivalidate.FieldDetail{Field: field, Message: "invalid"}
	}
	return nil
}

func validateLabelColor(color string) *apivalidate.FieldDetail {
	color = strings.TrimSpace(color)
	if len(color) > maxLabelColor || containsNewline(color) {
		return &apivalidate.FieldDetail{Field: "color", Message: "invalid"}
	}
	return nil
}

func validateCreateUserLabel(req *createUserLabelRequest) *apivalidate.ValidationError {
	var details []apivalidate.FieldDetail
	if d := validateLabelName("name", req.Name, true); d != nil {
		details = append(details, *d)
	}
	if d := validateLabelColor(req.Color); d != nil {
		details = append(details, *d)
	}
	if len(details) == 0 {
		return nil
	}
	return apivalidate.NewValidationError(details...)
}

func validateUpdateUserLabel(req *updateUserLabelRequest) *apivalidate.ValidationError {
	var details []apivalidate.FieldDetail
	if d := validateLabelName("name", req.Name, true); d != nil {
		details = append(details, *d)
	}
	if d := validateLabelColor(req.Color); d != nil {
		details = append(details, *d)
	}
	if len(details) == 0 {
		return nil
	}
	return apivalidate.NewValidationError(details...)
}

func validateListFoldersAccountID(accountID string) *apivalidate.ValidationError {
	if strings.TrimSpace(accountID) == "" {
		return apivalidate.NewValidationError(apivalidate.FieldDetail{
			Field: "account_id", Message: "required",
		})
	}
	return nil
}
