package notify

import (
	"bytes"
	"context"
	"net/url"
	"strconv"
	"strings"
	"text/template"

	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/perf/go/alerts"
	"go.skia.org/infra/perf/go/clustering2"
	"go.skia.org/infra/perf/go/config"
	"go.skia.org/infra/perf/go/git/provider"
	"go.skia.org/infra/perf/go/ui/frame"
)

const (
	defaultRegressionMarkdownSubject = `{{ .Alert.DisplayName }} - Regression found for {{ .Commit.Subject }}`
	defaultRegressionMarkdown        = `A Perf Regression ({{.Cluster.StepFit.Status}}) has been found at:

  {{.URL}}/g/t/{{.Commit.GitHash}}

For:

  Commit {{.CommitURL}}

With:

  - {{.Cluster.Num}} matching traces.
  - Direction {{.Cluster.StepFit.Status}}.

From Alert [{{ .Alert.DisplayName }}]({{.URL}}/a/?{{ .Alert.IDAsString }})
`
	defaultRegressionMissingMarkdownSubject = `{{ .Alert.DisplayName }} - Regression no longer found for {{ .Commit.Subject }}`
	defaultRegressionMissingMarkdown        = `The Perf Regression can no longer be detected. This issue is being automatically closed.
`
)

// MarkdownFormatter implement Formatter.
type MarkdownFormatter struct {
	commitRangeURITemplate                   string
	markdownTemplateNewRegression            *template.Template
	markdownTemplateNewRegressionSubject     *template.Template
	markdownTemplateRegressionMissing        *template.Template
	markdownTemplateRegressionMissingSubject *template.Template
}

// buildIDFromSubject is a template func for notify templates.
//
// Note that this is very specific to the android-x git repo where each commit
// subject is formatted as a single URL, for example:
//
//	https://android-build.googleplex.com/builds/jump-to-build/10768702
//
//	And the template func will extract "10768702" from the above subject.
//
// The implementation is robust and if the subject isn't in the right format
// then the empty string is returned.
func buildIDFromSubject(subject string) string {
	parts := strings.Split(strings.TrimSpace(subject), "/")
	n := len(parts)
	if n == 0 {
		return ""
	}
	return parts[n-1]
}

// NewMarkdownFormatter return a new MarkdownFormatter.
func NewMarkdownFormatter(commitRangeURITemplate string, notifyConfig *config.NotifyConfig) (MarkdownFormatter, error) {
	body := strings.Join(notifyConfig.Body, "\n")
	if body == "" {
		body = defaultRegressionMarkdown
	}
	subject := notifyConfig.Subject
	if subject == "" {
		subject = defaultRegressionMarkdownSubject
	}

	missingBody := strings.Join(notifyConfig.MissingBody, "\n")
	if missingBody == "" {
		missingBody = defaultRegressionMissingMarkdown
	}

	missingSubject := notifyConfig.MissingSubject
	if missingSubject == "" {
		missingSubject = defaultRegressionMissingMarkdownSubject
	}

	funcMap := template.FuncMap{
		"buildIDFromSubject": buildIDFromSubject,
	}

	markdownTemplateNewRegression, err := template.New("newRegressionMarkdown").Funcs(funcMap).Parse(body)
	if err != nil {
		return MarkdownFormatter{}, skerr.Wrapf(err, "compiling markdownTemplateNewRegression")
	}
	markdownTemplateNewRegressionSubject, err := template.New("newRegressionMarkdown").Funcs(funcMap).Parse(subject)
	if err != nil {
		return MarkdownFormatter{}, skerr.Wrapf(err, "compiling markdownTemplateNewRegressionSubject")
	}
	markdownTemplateRegressionMissing, err := template.New("regressionMissingMarkdown").Funcs(funcMap).Parse(missingBody)
	if err != nil {
		return MarkdownFormatter{}, skerr.Wrapf(err, "compiling markdownTemplateRegressionMissing")
	}
	markdownTemplateRegressionMissingSubject, err := template.New("regressionMissingMarkdown").Funcs(funcMap).Parse(missingSubject)
	if err != nil {
		return MarkdownFormatter{}, skerr.Wrapf(err, "compiling markdownTemplateRegressionMissingSubject")
	}

	return MarkdownFormatter{
		commitRangeURITemplate:                   commitRangeURITemplate,
		markdownTemplateNewRegression:            markdownTemplateNewRegression,
		markdownTemplateNewRegressionSubject:     markdownTemplateNewRegressionSubject,
		markdownTemplateRegressionMissing:        markdownTemplateRegressionMissing,
		markdownTemplateRegressionMissingSubject: markdownTemplateRegressionMissingSubject,
	}, nil
}

// wiewOnDashboard is the URL to view the regressing traces on the explore page.
func viewOnDashboard(cl *clustering2.ClusterSummary, URL string, frame *frame.FrameResponse) string {
	u, err := url.Parse(URL)
	if err != nil {
		// Fallback to a relative URL if the base URL is invalid.
		u = &url.URL{}
	}
	end := ""
	if frame != nil && frame.DataFrame != nil && len(frame.DataFrame.Header) > 0 {
		n := len(frame.DataFrame.Header)
		// Expand the time range by 1s to ensure inclusion of the last commit.
		end = strconv.Itoa(int(frame.DataFrame.Header[n-1].Timestamp + 1))
	}
	q := url.Values{
		"keys":         []string{cl.Shortcut},
		"xbaroffset":   []string{strconv.Itoa(int(cl.StepPoint.Offset))},
		"num_commits":  []string{"250"},
		"request_type": []string{"1"},
	}
	if end != "" {
		q.Set("end", end)
	}
	u.Path = "/e/"
	u.RawQuery = q.Encode()

	return u.String()
}

// FormatNewRegression implements Formatter.
func (h MarkdownFormatter) FormatNewRegression(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, URL string, frame *frame.FrameResponse) (string, string, error) {

	templateContext := &TemplateContext{
		URL:             URL,
		ViewOnDashboard: viewOnDashboard(cl, URL, frame),
		PreviousCommit:  previousCommit,
		Commit:          commit,
		CommitURL:       URLFromCommitRange(commit, previousCommit, h.commitRangeURITemplate),
		Alert:           alert,
		Cluster:         cl,
		ParamSet:        frame.DataFrame.ParamSet,
	}

	return h.FormatNewRegressionWithContext(templateContext)
}

// FormatNewRegressionWithContext formats the bug data for a new regression using the given templateContext instance.
func (h MarkdownFormatter) FormatNewRegressionWithContext(templateContext interface{}) (string, string, error) {
	var body bytes.Buffer
	if err := h.markdownTemplateNewRegression.Execute(&body, templateContext); err != nil {
		return "", "", skerr.Wrapf(err, "format Markdown body for a new regression")
	}
	var subject bytes.Buffer
	if err := h.markdownTemplateNewRegressionSubject.Execute(&subject, templateContext); err != nil {
		return "", "", skerr.Wrapf(err, "format Markdown subject for a new regression")
	}

	return body.String(), subject.String(), nil
}

// FormatRegressionMissing implements Formatter.
func (h MarkdownFormatter) FormatRegressionMissing(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, URL string, frame *frame.FrameResponse) (string, string, error) {
	templateContext := &TemplateContext{
		URL:             URL,
		ViewOnDashboard: viewOnDashboard(cl, URL, frame),
		PreviousCommit:  previousCommit,
		Commit:          commit,
		CommitURL:       URLFromCommitRange(commit, previousCommit, h.commitRangeURITemplate),
		Alert:           alert,
		Cluster:         cl,
		ParamSet:        frame.DataFrame.ParamSet,
	}

	return h.FormatRegressionMissingWithContext(templateContext)
}

// FormatRegressionMissingWithContext formats the bug data for a missing regression using the given template context instance.
func (h MarkdownFormatter) FormatRegressionMissingWithContext(templateContext interface{}) (string, string, error) {
	var body bytes.Buffer
	if err := h.markdownTemplateRegressionMissing.Execute(&body, templateContext); err != nil {
		return "", "", skerr.Wrapf(err, "format Markdown body for a regression that has gone missing")
	}
	var subject bytes.Buffer
	if err := h.markdownTemplateRegressionMissingSubject.Execute(&subject, templateContext); err != nil {
		return "", "", skerr.Wrapf(err, "format Markdown subject for regression that has gone missing")
	}
	return body.String(), subject.String(), nil
}

var _ Formatter = MarkdownFormatter{}
