package validation

import (
	"context"

	"code.justin.tv/eventbus/controlplane/internal/clients/servicecatalog"

	"github.com/aws/aws-sdk-go/aws/client"
	"github.com/pkg/errors"

	"code.justin.tv/eventbus/controlplane/internal/db"
)

const ErrServiceNotInCatalog = "service not found in service catalog"

type Service struct {
	*db.Service
	serviceCatalog servicecatalog.Client
}

func (s *Service) ID() string {
	return itemID(s)
}

func (s *Service) Type() string {
	return "Service"
}

func (s *Service) Attributes() []*ItemAttribute {
	return []*ItemAttribute{
		{
			Key:   "Name",
			Value: s.Name,
		},
		{
			Key:   "ServiceCatalogID",
			Value: s.ServiceCatalogID,
		},
		{
			Key:   "LDAPGroup",
			Value: s.LDAPGroup,
		},
	}
}

func (s *Service) Validate(ctx context.Context) (*Report, error) {
	_, err := s.serviceCatalog.Get(ctx, s.ServiceCatalogID)
	if err == servicecatalog.ErrDoesNotExist {
		// Because this is out of our control, never report ERROR for missing services in the service catalog
		return Warn(s, ErrServiceNotInCatalog), nil
	} else if err != nil {
		return nil, errors.Wrap(err, "could not fetch service from service catalog")
	}

	return Ok(s), nil
}

func Services(ctx context.Context, sess client.ConfigProvider, db db.DB, sc servicecatalog.Client) ([]Item, error) {
	services, err := db.Services(ctx)
	if err != nil {
		return nil, errors.Wrap(err, "could not fetch services")
	}

	items := make([]Item, len(services))
	for i, service := range services {
		items[i] = &Service{
			Service:        service,
			serviceCatalog: sc,
		}
	}
	return items, nil
}
