package v1

import (
	"context"

	"github.com/pingcap-inc/pchub/internal/apiserver/store"
	"github.com/pingcap-inc/pchub/internal/pkg/code"
	v1 "github.com/pingcap-inc/pchub/model/v1"
	"github.com/pingcap-inc/pchub/pkg/errors"
	"github.com/pingcap-inc/pchub/pkg/log"
)

type starResourceService struct {
	store store.Factory
}

type StarResourceSrv interface {
	List(ctx context.Context, ularkID string) ([]*v1.UserStarResource, error)
	ToggleStarResource(ctx context.Context, ularkID, mngID string) error
}

var _ StarResourceSrv = (*starResourceService)(nil)

func newStarResource(srv *service) *starResourceService {
	return &starResourceService{store: srv.store}
}

func (s *starResourceService) List(ctx context.Context, ularkID string) ([]*v1.UserStarResource, error) {
	res, err := s.store.UserStarResource().List(ctx, ularkID)
	if err != nil {
		return nil, err
	}

	for _, r := range res {
		p, err := s.store.CloudProvider().GetByID(ctx, r.Resource.ProviderID)
		if err != nil {
			log.L(ctx).Errorf("get cloud provider by id failed, err: %s", err.Error())

			continue
		}

		r.Resource.Provider = *p
	}

	return res, nil
}

func (s *starResourceService) ToggleStarResource(ctx context.Context, ularkID, mngID string) error {
	log.L(ctx).Infof("StarResourceSrv.ToggleStarResource Called, ularkID: %s, mngID: %s", ularkID, mngID)

	r, err := s.store.CloudResource().Get(ctx, &v1.CloudResource{ManagementID: mngID})
	if err != nil {
		return err
	}

	usr, err := s.store.UserStarResource().GetByUR(ctx, ularkID, r.ID)
	notFound := false
	if err != nil {
		coder := errors.ParseCoder(err)
		if coder.Code() != code.ErrRecordNotFound {
			e := errors.Wrap(err, "Error when exec UserStarResourceStore.GetByUR")
			log.L(ctx).Error(e.Error())

			return e
		}

		notFound = true
	}
	if usr.ID == 0 {
		notFound = true
	}

	if notFound {
		return s.store.UserStarResource().Create(ctx, ularkID, r.ID)
	}

	return s.store.UserStarResource().Delete(ctx, usr.ID)
}
