package contacts

import (
	"net/mail"
	"strconv"
	"strings"

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

const (
	maxRequestBody   = 64 << 10
	maxSyncTokenLen = 8192
)

func validateSyncToken(raw string) (string, *apivalidate.ValidationError) {
	raw = strings.TrimSpace(raw)
	if raw == "" {
		return "", nil
	}
	if len(raw) > maxSyncTokenLen {
		return "", apivalidate.NewValidationError(apivalidate.FieldDetail{
			Field: "sync_token", Message: "too long",
		})
	}
	if strings.ContainsAny(raw, "\r\n\x00") || strings.ContainsAny(raw, "<>&") {
		return "", apivalidate.NewValidationError(apivalidate.FieldDetail{
			Field: "sync_token", Message: "invalid",
		})
	}
	return raw, nil
}

func validateCreateContact(contact *nextcloud.Contact) *apivalidate.ValidationError {
	if strings.TrimSpace(contact.FullName) == "" {
		return apivalidate.NewValidationError(apivalidate.FieldDetail{
			Field: "full_name", Message: "required",
		})
	}
	return nil
}

func validateIfMatch(ifMatch string) *apivalidate.ValidationError {
	if strings.TrimSpace(ifMatch) == "" {
		return apivalidate.NewValidationError(apivalidate.FieldDetail{
			Field: "If-Match", Message: "required",
		})
	}
	if strings.ContainsAny(ifMatch, "\r\n") {
		return apivalidate.NewValidationError(apivalidate.FieldDetail{
			Field: "If-Match", Message: "invalid",
		})
	}
	return nil
}

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

func validateInteractionQuery(emailRaw, limitRaw string) (string, int, *apivalidate.ValidationError) {
	email := strings.TrimSpace(emailRaw)
	if email == "" {
		return "", 0, apivalidate.NewValidationError(apivalidate.FieldDetail{
			Field: "email", Message: "required",
		})
	}
	if len(email) > 320 || strings.ContainsAny(email, "\r\n") {
		return "", 0, apivalidate.NewValidationError(apivalidate.FieldDetail{
			Field: "email", Message: "invalid",
		})
	}
	parsed, err := mail.ParseAddress(email)
	if err != nil || parsed.Address == "" {
		return "", 0, apivalidate.NewValidationError(apivalidate.FieldDetail{
			Field: "email", Message: "invalid",
		})
	}

	limit := 20
	raw := strings.TrimSpace(limitRaw)
	if raw != "" {
		parsedLimit, err := strconv.Atoi(raw)
		if err != nil || parsedLimit < 1 || parsedLimit > 100 {
			return "", 0, apivalidate.NewValidationError(apivalidate.FieldDetail{
				Field: "limit", Message: "must be between 1 and 100",
			})
		}
		limit = parsedLimit
	}

	return parsed.Address, limit, nil
}
