package handler_utils

import (
	"encoding/json"
	"github.com/aws/aws-lambda-go/events"
	"gitlab.com/uafrica/go-utils/errors"
	"gitlab.com/uafrica/go-utils/logs"
	"reflect"
)

// ValidateSQSEndpoints checks that all SQS endpoints are correctly defined using one of the supported handler types
// return updated endpoints with additional information
func ValidateSQSEndpoints(endpoints map[string]interface{}) (map[string]interface{}, error) {
	countLegacy := 0
	countHandler := 0
	for messageType, handlerFunc := range endpoints {
		if messageType == "" {
			return nil, errors.Errorf("blank messageType")
		}
		if handlerFunc == nil {
			return nil, errors.Errorf("nil handler on %s", messageType)
		}

		if _, ok := handlerFunc.(func(req events.SQSEvent) (err error)); ok {
			// ok - leave as is - we support this legacyHandler
			countLegacy++
		} else {
			handler, err := NewSQSHandler(handlerFunc)
			if err != nil {
				return nil, errors.Wrapf(err, "%v has invalid handler %T", messageType, handlerFunc)
			}
			// replace the endpoint value so we can quickly call this handler
			endpoints[messageType] = handler
			logs.Info("%s: OK (request: %v)\n", messageType, handler.RecordType)
			countHandler++
		}
	}
	logs.Info("Checked %d legacy and %d new handlers\n", countLegacy, countHandler)
	return endpoints, nil
}

func GetRecord(message events.SQSMessage, recordType reflect.Type) (interface{}, error) {
	recordValuePtr := reflect.New(recordType)
	err := json.Unmarshal([]byte(message.Body), recordValuePtr.Interface())
	if err != nil {
		return nil, errors.Wrapf(err, "failed to JSON decode message body")
	}

	if validator, ok := recordValuePtr.Interface().(IValidator); ok {
		if err := validator.Validate(); err != nil {
			return nil, errors.Wrapf(err, "invalid message body")
		}
	}

	return recordValuePtr.Elem().Interface(), nil
}

type IValidator interface {
	Validate() error
}