package userbehavior

import (
	"context"

	larkim "github.com/larksuite/oapi-sdk-go/v3/service/im/v1"
	"github.com/tidbcloud/devops/entity"
	ubent "github.com/tidbcloud/devops/entity/userbehavior"
	"github.com/tidbcloud/devops/pkg/infra/utils/pointer"
	"github.com/tidbcloud/devops/pkg/infra/utils/repoopt"
	"github.com/tidbcloud/devops/pkg/service/userbehavior/repo"
)

func (s *svc) ListSubscriptions(ctx context.Context, param ListSubscriptionParam) ([]*ubent.Subscription, int64, error) {
	opts := []repoopt.Option{}

	if param.PerPage > 0 {
		opts = append(opts, repo.SubscriptionOpts.WithPager(param.Page, param.PerPage, false))
	}

	if param.Creator != nil {
		opts = append(opts, repo.SubscriptionOpts.ByEmail(*param.Creator))
	}

	if param.EventTp != nil {
		opts = append(opts, repo.SubscriptionOpts.IsUBEvent(*param.EventTp))
	}

	arr, err := s.repo.QuerySubscriptions(ctx, opts...)
	if err != nil {
		return arr, 0, err
	}
	return arr, int64(len(arr)), err
}

func (s *svc) GetSubscription(ctx context.Context, id uint64) (*ubent.Subscription, error) {
	return s.repo.LoadSubscription(ctx, id)
}

func (s *svc) CreateSubscription(ctx context.Context, param CreateSubscriptionParam) (*uint64, error) {
	ent := &ubent.Subscription{
		SubscribeType:      param.SubscribeType,
		EventType:          param.EventType,
		Template:           param.Template,
		Selector:           param.Selector,
		Creator:            param.Creator,
		Name:               param.Name,
		LarkChats:          param.LarkChats,
		OnlyPaidTenant:     param.OnlyPaidTenant,
		OnlyExternalTenant: param.OnlyExternalTenant,
	}
	err := s.repo.SaveSubscription(ctx, ent)
	return nil, err
}

func (s *svc) DeleteSubscription(ctx context.Context, id uint64) error {
	err := s.repo.DeleteSubscription(ctx, id)
	return err
}

func (s *svc) EditSubscription(ctx context.Context, id uint64, param EditSubscriptionParam) error {
	ent := &ubent.Subscription{
		ID:            id,
		Name:          param.Name,
		SubscribeType: param.SubscribeType,
		EventType:     param.EventType,
		Template:      param.Template,
		Selector:      param.Selector,
		LarkChats:     param.LarkChats,
	}
	err := s.repo.PatchSubscription(ctx, ent)
	return err
}

func (s *svc) ChangeSubscriptionAvailability(ctx context.Context, available bool) error {
	return nil
}

func (s *svc) SendMockEventToSubscription(ctx context.Context, id uint64) error {
	sub, err := s.repo.LoadSubscription(ctx, id)
	if err != nil {
		return err
	}

	chats := sub.LarkChats

	for _, chatSimplified := range chats {
		chat, err := s.repo.LoadChat(ctx, chatSimplified.ID)
		if err != nil {
			s.logger.Info("fail to load chat", "chat_id", chatSimplified.ID, "err", err)
		}

		var mockText string

		if len(sub.Template) == 0 {
			mockText = "**mock message**: event messages will be sent here."
		} else {
			mockText = sub.Template
		}

		cardContent, err := s.buildCard(mockText, "").String()
		if err != nil {
			return err
		}

		if chat.IsExternal {
			if chat.ChatURL == nil {
				// shouldn't be here
				continue
			}
			s.externalLarkCli.SendCard(ctx, *chat.ChatURL, cardContent)
			continue
		}

		if chat.ChatID == nil {
			// Shouldn't be here
			continue
		}

		req := larkim.NewCreateMessageReqBuilder().
			ReceiveIdType("chat_id").
			Body(&larkim.CreateMessageReqBody{
				ReceiveId: pointer.Pointer(*chat.ChatID),
				MsgType:   pointer.Pointer("interactive"),
				Content:   &cardContent,
			}).Build()

		s.larkCliSet.Raw.Im.Message.Create(ctx, req)
	}
	return nil
}

func (s *svc) GetLarkChatOptions(ctx context.Context) ([]*entity.LarkChatSimplified, error) {
	arr, err := s.repo.QueryChatSimplifieds(ctx)
	return arr, err
}

func (s *svc) AddExternalLarkChat(ctx context.Context, param AddExternalLarkChatParam) error {
	ent := &entity.LarkChat{
		Name:       &param.Name,
		IsExternal: true,
		ChatURL:    &param.ChatURL,
		AvatarURL:  param.AvatarURL,
	}
	err := s.repo.SaveChat(ctx, ent)
	return err
}
