package services

import (
	"context"
	"database/sql"
	"testing"
	"time"

	"quyun/v2/app/commands/testx"
	app_dto "quyun/v2/app/http/v1/dto"
	"quyun/v2/app/requests"
	"quyun/v2/database"
	"quyun/v2/database/models"
	"quyun/v2/pkg/consts"

	. "github.com/smartystreets/goconvey/convey"
	"github.com/stretchr/testify/suite"
	"go.ipao.vip/atom/contracts"
	"go.uber.org/dig"
)

type NotificationTestSuiteInjectParams struct {
	dig.In

	DB       *sql.DB
	Initials []contracts.Initial `group:"initials"`
}

type NotificationTestSuite struct {
	suite.Suite
	NotificationTestSuiteInjectParams
}

func Test_Notification(t *testing.T) {
	providers := testx.Default().With(Provide)

	testx.Serve(providers, t, func(p NotificationTestSuiteInjectParams) {
		suite.Run(t, &NotificationTestSuite{NotificationTestSuiteInjectParams: p})
	})
}

func (s *NotificationTestSuite) Test_CRUD() {
	Convey("Notification CRUD", s.T(), func() {
		ctx := s.T().Context()
		database.Truncate(ctx, s.DB, models.TableNameNotification)

		tenantID := int64(1)
		uID := int64(100)
		ctx = context.WithValue(ctx, consts.CtxKeyUser, uID)

		Convey("should send notification", func() {
			err := Notification.Send(ctx, tenantID, uID, "system", "Welcome", "Hello World")
			So(err, ShouldBeNil)

			var list *requests.Pager
			for i := 0; i < 5; i++ {
				list, err = Notification.List(ctx, tenantID, uID, 1, "")
				So(err, ShouldBeNil)
				if list.Total > 0 {
					break
				}
				time.Sleep(50 * time.Millisecond)
			}
			So(list.Total, ShouldEqual, 1)

			items := list.Items.([]app_dto.Notification)
			So(len(items), ShouldEqual, 1)
			So(items[0].Title, ShouldEqual, "Welcome")

			// Mark Read
			// Need ID
			n, _ := models.NotificationQuery.WithContext(ctx).Where(models.NotificationQuery.UserID.Eq(uID)).First()
			err = Notification.MarkRead(ctx, tenantID, uID, n.ID)
			So(err, ShouldBeNil)

			nReload, _ := models.NotificationQuery.WithContext(ctx).Where(models.NotificationQuery.ID.Eq(n.ID)).First()
			So(nReload.IsRead, ShouldBeTrue)
		})
	})
}
