package notify

import (
	"context"
	"fmt"
	"maps"
	"slices"
	"strconv"

	larkutil "github.com/tidbcloud/devops/pkg/infra/clients/larkcli/util"
	"github.com/tidbcloud/devops/pkg/infra/consts"
)

type ApprovalStartParam struct {
	Env        consts.Environment
	Name       string
	Overview   map[string]string
	Parameters map[string]string
	DetailLink string
	Reason     string
}

func (m ApprovalStartParam) Message(cards MessageCardSet) (larkutil.IMMessage, error) {

	return larkutil.IMMessageCardTemplate{
		MType: "template",
		Data: larkutil.IMMessageCardTemplateData{
			ID: cards.ApprovalStart,
			Vars: map[string]string{
				"name":        m.Name,
				"overviews":   larkutil.FormatItems(buildParamsToItems(m.Overview), "", ""),
				"parameters":  larkutil.FormatItems(buildParamsToItems(m.Parameters), "", ""),
				"detail_link": m.DetailLink,
				"env":         string(m.Env),
				"reason":      m.Reason,
			},
		},
	}, nil
}

type ApprovalEndParam struct {
	Env        consts.Environment
	Name       string
	Overview   map[string]string
	Parameters map[string]string
	DetailLink string
	Result     string
	Reason     string
}

func (m ApprovalEndParam) Message(cards MessageCardSet) (larkutil.IMMessage, error) {
	return larkutil.IMMessageCardTemplate{
		MType: "template",
		Data: larkutil.IMMessageCardTemplateData{
			ID: cards.ApprovalEnd,
			Vars: map[string]string{
				"name":        m.Name,
				"overviews":   larkutil.FormatItems(buildParamsToItems(m.Overview), "", ""),
				"parameters":  larkutil.FormatItems(buildParamsToItems(m.Parameters), "", ""),
				"detail_link": m.DetailLink,
				"env":         string(m.Env),
				"result":      m.Result,
				"reason":      m.Reason,
			},
		},
	}, nil
}

type ApprovalTaskStartParam struct {
	Env            consts.Environment
	Name           string
	ApplicantEmail string
	ApprovalID     uint64
	Overview       map[string]string
	Parameters     map[string]string
	DetailLink     string
	Reason         string
	Approver       LarkUser
}

func (m ApprovalTaskStartParam) Message(cards MessageCardSet) (larkutil.IMMessage, error) {
	atApprover := ""
	if m.Approver.LarkID != nil && *m.Approver.LarkID != "" {
		atApprover = larkutil.AtUserInCard(*m.Approver.LarkID)
	}

	return larkutil.IMMessageCardTemplate{
		MType: "template",
		Data: larkutil.IMMessageCardTemplateData{
			ID: cards.ApprovalTaskStart,
			Vars: map[string]string{
				"name":            m.Name,
				"applicant_email": m.ApplicantEmail,
				"overviews":       larkutil.FormatItems(buildParamsToItems(m.Overview), "", ""),
				"parameters":      larkutil.FormatItems(buildParamsToItems(m.Parameters), "", ""),
				"detail_link":     m.DetailLink,
				"env":             string(m.Env),
				"approval_id":     strconv.FormatUint(m.ApprovalID, 10),
				"reason":          m.Reason,
				"at_approver":     atApprover,
			},
		},
	}, nil
}

type ApprovalTaskEndParam struct {
	Env            consts.Environment
	Name           string
	ApplicantEmail string
	Overview       map[string]string
	Parameters     map[string]string
	DetailLink     string
	Result         string
	Reason         string
}

func (m ApprovalTaskEndParam) Message(cards MessageCardSet) (larkutil.IMMessage, error) {
	return larkutil.IMMessageCardTemplate{
		MType: "template",
		Data: larkutil.IMMessageCardTemplateData{
			ID: cards.ApprovalTaskEnd,
			Vars: map[string]string{
				"name":            m.Name,
				"applicant_email": m.ApplicantEmail,
				"overviews":       larkutil.FormatItems(buildParamsToItems(m.Overview), "", ""),
				"parameters":      larkutil.FormatItems(buildParamsToItems(m.Parameters), "", ""),
				"detail_link":     m.DetailLink,
				"env":             string(m.Env),
				"result":          m.Result,
				"reason":          m.Reason,
			},
		},
	}, nil
}

type ApprovalCCParam struct {
	Env            consts.Environment
	Name           string
	ApplicantEmail string
	Overview       map[string]string
	Parameters     map[string]string
	DetailLink     string
	Result         string
	Reason         string
}

func (m ApprovalCCParam) Message(cards MessageCardSet) (larkutil.IMMessage, error) {
	return larkutil.IMMessageCardTemplate{
		MType: "template",
		Data: larkutil.IMMessageCardTemplateData{
			ID: cards.ApprovalCC,
			Vars: map[string]string{
				"name":            m.Name,
				"applicant_email": m.ApplicantEmail,
				"overviews":       larkutil.FormatItems(buildParamsToItems(m.Overview), "", ""),
				"parameters":      larkutil.FormatItems(buildParamsToItems(m.Parameters), "", ""),
				"detail_link":     m.DetailLink,
				"env":             string(m.Env),
				"result":          m.Result,
				"reason":          m.Reason,
			},
		},
	}, nil
}

func (c *client) ApprovalStart(ctx context.Context, userID string, param ApprovalStartParam) (*string /*msg id*/, error) {
	return c.SendMessage(ctx, ReceiveTypeUser, userID, param)
}

func (c *client) ApprovalEnd(ctx context.Context, userID string, param ApprovalEndParam) (*string /*msg id*/, error) {
	return c.SendMessage(ctx, ReceiveTypeUser, userID, param)
}

func (c *client) ApprovalTaskStart(ctx context.Context, userID string, param ApprovalTaskStartParam) (*string /*msg id*/, error) {
	return c.SendMessage(ctx, ReceiveTypeUser, userID, param)
}

func (c *client) ApprovalTaskEnd(ctx context.Context, msgID string, param ApprovalTaskEndParam) error {
	return c.PatchMessage(ctx, msgID, param)
}

func (c *client) ApprovalCC(ctx context.Context, userID string, param ApprovalCCParam) (*string /*msg id*/, error) {
	return c.SendMessage(ctx, ReceiveTypeUser, userID, param)
}

func buildParamsToItems(param map[string]string) []string {
	paramItems := make([]string, 0, len(param))
	for _, key := range slices.Sorted(maps.Keys(param)) {
		paramItems = append(paramItems, fmt.Sprintf("%s: %s", key, param[key]))
	}
	return paramItems
}
