package lark

import (
	"strings"

	larkim "github.com/tidbcloud/aisupport/packages/sdk-go/infra/lark/client/im"
	larkutil "github.com/tidbcloud/aisupport/packages/sdk-go/infra/lark/client/util"
	strutil "github.com/tidbcloud/aisupport/packages/sdk-go/infra/utils/container/str"
)

const (
	cardTextTag                         = "plain_text"
	textTagTag                          = "text_tag"
	markdownElementTag                  = "markdown"
	collapsiblePanelElementTag          = "collapsible_panel"
	collapsiblePanelDescriptionMaxRunes = 50
	taskIDTagColor                      = "blue"
)

type defaultRenderer struct{}

func (defaultRenderer) Result(taskID, content string) (larkim.Message, error) {
	return renderCard("Result", "green", taskID, markdownElement(content))
}

func (defaultRenderer) Failed(taskID, content string) (larkim.Message, error) {
	return renderCard("Failed", "red", taskID, markdownElement(content))
}

func (defaultRenderer) Rejected(taskID, content string) (larkim.Message, error) {
	return renderCard("Rejected", "orange", taskID, markdownElement(content))
}

func (defaultRenderer) Commentary(taskID, content, latestMessage string) (larkim.Message, error) {
	return renderCard("Commentary", "blue", taskID, larkutil.CardCollapsiblePanelElement{
		Tag:      collapsiblePanelElementTag,
		Expanded: false,
		Header: larkutil.CardElementHeader{
			Title: larkutil.CardText{Tag: cardTextTag, Content: collapsiblePanelDescription(latestMessage)},
		},
		Elements: []larkutil.CardElement{markdownElement(content)},
	})
}

func renderCard(title, color, taskID string, elements ...larkutil.CardElement) (larkim.Message, error) {
	content, err := larkutil.RenderCard(larkutil.Card{
		Config: larkutil.CardConfig{WideScreenMode: true},
		Header: larkutil.CardHeader{
			Title: larkutil.CardText{Tag: cardTextTag, Content: title},
			TextTagList: []larkutil.CardTextTag{{
				Tag:   textTagTag,
				Text:  larkutil.CardText{Tag: cardTextTag, Content: taskID},
				Color: taskIDTagColor,
			}},
			Template: color,
		},
		Elements: elements,
	})
	if err != nil {
		return nil, err
	}
	return rawCard(content), nil
}

func markdownElement(content string) larkutil.CardMarkdownElement {
	return larkutil.CardMarkdownElement{Tag: markdownElementTag, Content: content}
}

func collapsiblePanelDescription(content string) string {
	content = strings.ReplaceAll(content, "\n", " ")
	return "< " + strutil.TruncateRunes(content, collapsiblePanelDescriptionMaxRunes) + " ..."
}

type rawCard string

func (rawCard) Type() larkim.MessageType {
	return larkim.MessageTypeInteractive
}

func (c rawCard) MarshalJSON() ([]byte, error) {
	return []byte(c), nil
}
