package notify

import (
	"context"
	"fmt"
	"os"
	"testing"
	"time"

	opent "github.com/tidbcloud/devops/entity/operation"
	relent "github.com/tidbcloud/devops/entity/release"
	"github.com/tidbcloud/devops/pkg/infra/utils/container"
	"github.com/tidbcloud/devops/pkg/infra/utils/pointer"
	"github.com/tidbcloud/devops/pkg/infra/utils/test"

	lark "github.com/larksuite/oapi-sdk-go/v3"
	larkcontact "github.com/larksuite/oapi-sdk-go/v3/service/contact/v3"
	larkim "github.com/larksuite/oapi-sdk-go/v3/service/im/v1"
	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)

func TestLarkClient(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Approval Lark Client")
}

var _ = Describe("[Approval Lark Client]", func() {
	var larkCli *lark.Client
	var cli Notification

	BeforeEach(func() {
		var err error
		appCode := os.Getenv("LARK_APP_CODE")
		appSecret := os.Getenv("LARK_APP_SECRET")
		larkCli = lark.NewClient(appCode, appSecret)

		cli = New(larkCli, MsgCardSet)
		Expect(err).To(BeNil())
	})

	Context("[Release Related]", func() {
		var chatID string

		BeforeEach(func() {
			chatID = "oc_56e243c8348ed11d9c3fdc4dda45b19e"
		})

		PIt("create release message", func() {
			param := ReleaseTopicParam{
				ChangeName:      "change_name",
				ChangeLink:      fmt.Sprintf("%s/%d", "https://ops-dev.tidbcloud.com/deployment", 6),
				ApplicationName: "devops",
				WindowStartAt:   *test.ParseTimeOrDie(time.DateTime, "2023-06-12 11:00:00"),
				WindowEndAt:     *test.ParseTimeOrDie(time.DateTime, "2023-06-12 12:00:00"),
				Applicant: LarkUser{
					Email: "sihao.yu@pingcap.com",
				},
				ChangeItems: []ReleaseTopicParamChangeItem{
					{
						ChangeItem: &relent.ReleaseTicket{
							ReleaseTicketInRepo: relent.ReleaseTicketInRepo{
								Name:          "DM-1234",
								AssigneeEmail: "sihao.yu@pingcap.com",
							},
						},
						NotifyUsers: container.Set[string]{},
					},
				},
			}

			ctx := context.Background()
			id, err := cli.ReleaseTopic(ctx, chatID, param)
			Expect(err).To(BeNil())
			Expect(id).ToNot(BeZero())
			fmt.Println(*id)

		})

		PIt("reply deployment message", func() {
			msgID := "om_c78107b182748380f4dfe9e07c146c9a"
			param := ReleaseDeploymentParam{
				Order: 0,
				Regions: []relent.RegionName{"aws-us-west-2", "gcp-us-west1", "gcp-us-west1",
					"gcp-us-west1", "gcp-us-west1", "gcp-us-west1", "gcp-us-west1"},
				Method: relent.ChangeDeployMethodArgoCD,
				Info: relent.ChangeDeployInfo{
					ArgoCD: &relent.ChangeDeployArgoCD{
						DeployPRs: []relent.GithubPR{
							{
								RepoOwner: "tidbcloud",
								RepoName:  "devops",
								PRNumber:  1,
							},
						},
					},
				},
			}

			ctx := context.Background()
			rid, err := cli.ReleaseDeployment(ctx, msgID, param)
			Expect(err).To(BeNil())
			Expect(rid).ToNot(BeZero())
		})

		PIt("reply message", func() {
			msgID := "om_c78107b182748380f4dfe9e07c146c9a"
			param := TextMessageParam("Please remember to close this change, as 24 hours have passed since deployments.")

			ctx := context.Background()
			rid, err := cli.ReplyMessage(ctx, msgID, param, true)
			Expect(err).To(BeNil())
			Expect(rid).ToNot(BeZero())
		})
	})

	Context("[Maintenace Related]", func() {
		var chatID string

		BeforeEach(func() {
			chatID = "oc_63830fd3b7cc1361106442218c9d9f78"
		})

		PIt("MaintenanceTaskRunning", func() {
			param := MaintenanceTaskRunningParam{
				ProjectID: 1372813089208341302,
				Clusters: []uint64{
					1379661944646225504,
					1379661944646255401,
				},
				ScheduleTime: time.Now(),
				DetailLink:   "",
			}

			ctx := context.Background()
			id, err := cli.MaintenanceTaskRunning(ctx, chatID, param)
			Expect(err).To(BeNil())
			Expect(id).ToNot(BeZero())
			fmt.Println(*id)
		})

		PIt("MaintenanceTaskClosed", func() {
			param := MaintenanceTaskClosedParam{
				ProjectID:  1372813089208341302,
				DetailLink: "",
			}

			ctx := context.Background()
			id, err := cli.MaintenanceTaskClosed(ctx, chatID, param)
			Expect(err).To(BeNil())
			Expect(id).ToNot(BeZero())
			fmt.Println(*id)
		})
	})

	Context("[Operation Related]", func() {
		PIt("OperationNotify", func() {
			param := OperationNotifyParam{
				InstanceID: 157,
				Operation:  "ModifyClusterVolumeManually",
				Reason:     "test",
				Params: map[opent.ParamName]string{
					"volume_size": "100",
				},
				Applicant: LarkUser{
					LarkID: pointer.Pointer("ou_bf5c6ef526f9ea424106dfd81de7415b"),
				},
				OnCallers: []LarkUser{
					{
						LarkID: pointer.Pointer("ou_1c5eac1af60a42725ef034886a6f87e6"),
					},
				},
				DetailURL: "https://ops-dev.tidbcloud.com/operations/157",
			}

			ctx := context.Background()
			err := cli.SendMessageViaWebhook(ctx, "xxx", param)
			Expect(err).To(BeNil())
		})
	})

	Context("[Approval Related]", func() {

		PIt("ApprovalNotify", func() {
			param := ApprovalTaskStartParam{
				Env:            "staging",
				Name:           "test",
				ApplicantEmail: "sihao.yu@pingcap.com",
				Parameters: map[string]string{
					"data": "test",
				},
				DetailLink: "https://ops-dev.tidbcloud.com/operations/157",
				Reason:     "xxx",
			}

			ctx := context.Background()
			id, err := cli.ApprovalTaskStart(ctx, "9766g439", param)
			Expect(err).To(BeNil())
			Expect(id).ToNot(BeZero())
			fmt.Println(*id)
		})

		PIt("ApprovalDone", func() {
			msgID := "om_0afbf42ceb1e3ebcfa535c83b2e36689"
			param := ApprovalTaskEndParam{
				Env:            "dev",
				Name:           "test",
				ApplicantEmail: "sihao.yu@pingcap.com",
				Parameters: map[string]string{
					"data": "test",
				},
				DetailLink: "https://ops-dev.tidbcloud.com/operations/157",
				Result:     "Approved",
			}

			ctx := context.Background()
			err := cli.ApprovalTaskEnd(ctx, msgID, param)
			Expect(err).To(BeNil())
		})
	})

	Context("Have a Try", func() {
		PIt("get chats id", func() {
			ctx := context.Background()
			req := larkim.NewListChatReqBuilder().PageSize(100).Build()

			resp, err := larkCli.Im.Chat.List(ctx, req)
			Expect(err).To(BeNil())
			fmt.Println(test.MarshalIndentOrDie(resp))
		})

		PIt("send message", func() {
			chatID := "oc_4c71f3d4dffababccd6d30793f9bef9b"
			ctx := context.Background()
			req := larkim.NewCreateMessageReqBuilder().
				ReceiveIdType("chat_id").
				Body(&larkim.CreateMessageReqBody{
					ReceiveId: pointer.Pointer(chatID),
					MsgType:   pointer.Pointer("text"),
					Content:   pointer.Pointer("{\"text\":\" test content\"}"),
				}).Build()
			resp, err := larkCli.Im.Message.Create(ctx, req)
			Expect(err).To(BeNil())
			fmt.Println(test.MarshalIndentOrDie(resp))
		})

		PIt("resp message", func() {
			ctx := context.Background()
			req := larkim.NewReplyMessageReqBuilder().
				MessageId("om_ce90abbdcb2b1424fae7226794a093b6").
				Body(&larkim.ReplyMessageReqBody{
					MsgType: pointer.Pointer("text"),
					Content: pointer.Pointer("{\"text\":\" test reply\"}"),
				}).Build()
			resp, err := larkCli.Im.Message.Reply(ctx, req)
			Expect(err).To(BeNil())
			fmt.Println(test.MarshalIndentOrDie(resp))
		})

		PIt("get lark id", func() {
			ctx := context.Background()
			req := larkcontact.NewBatchGetIdUserReqBuilder().
				UserIdType("user_id").
				Body(&larkcontact.BatchGetIdUserReqBody{
					Emails: []string{"lijiamin@pingcap.com"},
				}).Build()
			resp, err := larkCli.Contact.User.BatchGetId(ctx, req)
			Expect(err).To(BeNil())
			fmt.Println(test.MarshalIndentOrDie(resp))

			req2 := larkcontact.NewGetUserReqBuilder().
				UserIdType("user_id").
				UserId(*resp.Data.UserList[0].UserId).
				Build()
			resp2, err := larkCli.Contact.User.Get(ctx, req2)
			Expect(err).To(BeNil())
			fmt.Println(test.MarshalIndentOrDie(resp2))
		})
	})

})
