// Package notify is a package for sending notifications.
package notify

import (
	"context"
	"io/fs"

	"go.skia.org/infra/go/paramtools"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/perf/go/alerts"
	ag "go.skia.org/infra/perf/go/anomalygroup/notifier"
	"go.skia.org/infra/perf/go/clustering2"
	"go.skia.org/infra/perf/go/config"
	"go.skia.org/infra/perf/go/dataframe"
	"go.skia.org/infra/perf/go/git/provider"
	"go.skia.org/infra/perf/go/ingest/format"
	perf_issuetracker "go.skia.org/infra/perf/go/issuetracker"
	"go.skia.org/infra/perf/go/notify/common"
	"go.skia.org/infra/perf/go/notifytypes"
	"go.skia.org/infra/perf/go/stepfit"
	"go.skia.org/infra/perf/go/tracestore"
	"go.skia.org/infra/perf/go/types"
	"go.skia.org/infra/perf/go/ui/frame"
)

// Formatter has implementations for both HTML and Markdown.
type Formatter interface {
	// Return body and subject.
	FormatNewRegression(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, URL string, frame *frame.FrameResponse) (string, string, error)
	FormatRegressionMissing(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, URL string, frame *frame.FrameResponse) (string, string, error)
}

// Transport has implementations for email, issuetracker, and the noop implementation.
type Transport interface {
	SendNewRegression(ctx context.Context, alert *alerts.Alert, body, subject string) (threadingReference string, err error)
	SendRegressionMissing(ctx context.Context, threadingReference string, alert *alerts.Alert, body, subject string) (err error)
	UpdateRegressionNotification(ctx context.Context, alert *alerts.Alert, body, notificationId string) (err error)
}

const (
	fromAddress = "alertserver@skia.org"
)

// TemplateContext is used in expanding the message templates.
type TemplateContext struct {
	// URL is the root URL of the Perf instance.
	URL string

	// ViewOnDashboard is the URL to view the regressing traces on the explore
	// page.
	ViewOnDashboard string

	// PreviousCommit is the previous commit the regression was found at.
	//
	// All commits that might be blamed for causing the regression
	// are in the range `(PreviousCommit, Commit]`, that is inclusive of
	// Commit but exclusive of PreviousCommit.
	PreviousCommit provider.Commit

	// Commit is the commit the regression was found at.
	Commit provider.Commit

	// CommitURL is a URL that points to the above Commit. The value of this URL
	// can be controlled via the `--commit_range_url` flag.
	CommitURL string

	// Alert is the configuration for the alert that found the regression.
	Alert *alerts.Alert

	// Cluster is all the information found about the regression.
	Cluster *clustering2.ClusterSummary

	// ParamSet for all the matching traces.
	ParamSet paramtools.ReadOnlyParamSet
}

// Notifier provides an interface for regression notification functions
type Notifier interface {
	// RegressionFound sends a notification for the given cluster found at the given commit.
	RegressionFound(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, frame *frame.FrameResponse, regressionID string) (string, error)

	// RegressionMissing sends a notification that a previous regression found for
	// the given cluster found at the given commit has disappeared after more data
	// has arrived.
	RegressionMissing(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, frame *frame.FrameResponse, threadingReference string) error

	// ExampleSend sends an example for dummy data for the given alerts.Config.
	ExampleSend(ctx context.Context, alert *alerts.Alert) error

	UpdateNotification(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, frame *frame.FrameResponse, notificationId string) error
}

// defaultNotifier sends notifications.
type defaultNotifier struct {
	notificationDataProvider NotificationDataProvider

	formatter Formatter

	transport Transport

	// url is the URL of this instance of Perf.
	url string

	traceStore tracestore.TraceStore

	fs fs.FS
}

// newNotifier returns a newNotifier Notifier.
func newNotifier(notificationDataProvider NotificationDataProvider, formatter Formatter, transport Transport, url string, traceStore tracestore.TraceStore, fs fs.FS) Notifier {
	return &defaultNotifier{
		notificationDataProvider: notificationDataProvider,
		formatter:                formatter,
		transport:                transport,
		url:                      url,
		traceStore:               traceStore,
		fs:                       fs,
	}
}

// RegressionFound sends a notification for the given cluster found at the given commit. Where to send it is defined in the alerts.Config.
func (n *defaultNotifier) RegressionFound(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, frame *frame.FrameResponse, regressionID string) (string, error) {
	metadata, err := n.getRegressionMetadata(ctx, commit, previousCommit, alert, cl, n.url, frame)
	if err != nil {
		return "", skerr.Wrapf(err, "Getting regression metadata.")
	}
	notificationData, err := n.notificationDataProvider.GetNotificationDataRegressionFound(ctx, *metadata)
	if err != nil {
		return "", err
	}
	threadingReference, err := n.transport.SendNewRegression(ctx, alert, notificationData.Body, notificationData.Subject)
	if err != nil {
		return "", skerr.Wrapf(err, "sending new regression message")
	}

	return threadingReference, nil
}

// RegressionMissing sends a notification that a previous regression found for
// the given cluster found at the given commit has disappeared after more data
// has arrived. Where to send it is defined in the alerts.Config.
func (n *defaultNotifier) RegressionMissing(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, frame *frame.FrameResponse, threadingReference string) error {
	metadata, err := n.getRegressionMetadata(ctx, commit, previousCommit, alert, cl, n.url, frame)
	if err != nil {
		return skerr.Wrapf(err, "Getting regression metadata.")
	}
	notificationData, err := n.notificationDataProvider.GetNotificationDataRegressionMissing(ctx, *metadata)
	if err != nil {
		return err
	}
	if err := n.transport.SendRegressionMissing(ctx, threadingReference, alert, notificationData.Body, notificationData.Subject); err != nil {
		return skerr.Wrapf(err, "sending regression missing message")
	}

	return nil
}

// ExampleSend sends an example for dummy data for the given alerts.Config.
func (n *defaultNotifier) ExampleSend(ctx context.Context, alert *alerts.Alert) error {
	commit := provider.Commit{
		Subject:   "An example commit use for testing.",
		URL:       "https://skia.googlesource.com/skia/+show/d261e1075a93677442fdf7fe72aba7e583863664",
		GitHash:   "d261e1075a93677442fdf7fe72aba7e583863664",
		Timestamp: 1498176000,
	}

	previousCommit := provider.Commit{
		Subject:   "An example previous commit to use for testing.",
		URL:       "https://skia.googlesource.com/skia/+/fb49909acafba5e031b90a265a6ce059cda85019",
		GitHash:   "fb49909acafba5e031b90a265a6ce059cda85019",
		Timestamp: 1687824470,
	}

	cl := &clustering2.ClusterSummary{
		Num: 10,
		StepFit: &stepfit.StepFit{
			Status: stepfit.HIGH,
		},
		StepPoint: &dataframe.ColumnHeader{
			Offset:    2,
			Timestamp: 1498176000,
		},
	}

	frame := &frame.FrameResponse{
		DataFrame: &dataframe.DataFrame{
			Header: []*dataframe.ColumnHeader{
				{Offset: 1, Timestamp: 1687824470},
				{Offset: 2, Timestamp: 1498176000},
			},
			ParamSet: paramtools.ReadOnlyParamSet{
				"device_name": []string{"sailfish", "sargo", "wembley"},
			},
		},
	}

	threadingReference, err := n.RegressionFound(ctx, commit, previousCommit, alert, cl, frame, "")
	if err != nil {
		return skerr.Wrap(err)
	}
	err = n.RegressionMissing(ctx, commit, previousCommit, alert, cl, frame, threadingReference)
	if err != nil {
		return skerr.Wrap(err)
	}
	err = n.UpdateNotification(ctx, commit, previousCommit, alert, cl, frame, threadingReference)
	if err != nil {
		return skerr.Wrap(err)
	}
	return nil
}

func (n *defaultNotifier) UpdateNotification(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, frame *frame.FrameResponse, notificationId string) error {
	metadata, err := n.getRegressionMetadata(ctx, commit, previousCommit, alert, cl, n.url, frame)
	if err != nil {
		return err
	}
	notificationData, err := n.notificationDataProvider.GetNotificationDataRegressionFound(ctx, *metadata)
	if err != nil {
		return err
	}
	return n.transport.UpdateRegressionNotification(ctx, alert, notificationData.Body, notificationId)
}

// New returns a Notifier of the selected type.
func New(ctx context.Context, cfg *config.NotifyConfig, itCfg *config.IssueTrackerConfig, URL, commitRangeURITemplate string, traceStore tracestore.TraceStore, fs fs.FS) (Notifier, error) {
	formatter, err := getFormatter(cfg, commitRangeURITemplate)
	if err != nil {
		return nil, skerr.Wrap(err)
	}
	var notificationDataProvider NotificationDataProvider
	switch cfg.NotificationDataProvider {
	case notifytypes.DefaultNotificationProvider:
		notificationDataProvider = newDefaultNotificationProvider(formatter)
	case notifytypes.AndroidNotificationProvider:
		notificationDataProvider, err = NewAndroidNotificationDataProvider(commitRangeURITemplate, cfg)
		if err != nil {
			return nil, skerr.Wrap(err)
		}
	}

	switch cfg.Notifications {
	case notifytypes.None:
		return newNotifier(notificationDataProvider, formatter, NewNoopTransport(), URL, traceStore, fs), nil
	case notifytypes.HTMLEmail:
		return newNotifier(notificationDataProvider, formatter, NewEmailTransport(), URL, traceStore, fs), nil
	case notifytypes.MarkdownIssueTracker:
		tracker, err := NewIssueTrackerTransport(ctx, cfg)
		if err != nil {
			return nil, skerr.Wrap(err)
		}
		return newNotifier(notificationDataProvider, formatter, tracker, URL, traceStore, fs), nil
	case notifytypes.ChromeperfAlerting:
		return NewChromePerfNotifier(ctx, nil)
	case notifytypes.AnomalyGrouper:
		if itCfg == nil || itCfg.IssueTrackerAPIKeySecretProject == "" || itCfg.IssueTrackerAPIKeySecretName == "" {
			return nil, skerr.Fmt("Invalid issue tracker configs. It is required by anomalygroup notifier type.")
		}
		perfIssueTracker, err := perf_issuetracker.NewIssueTracker(ctx, *itCfg)
		if err != nil {
			return nil, skerr.Wrap(err)
		}
		return ag.NewAnomalyGroupNotifier(ctx, nil, perfIssueTracker), nil
	default:
		return nil, skerr.Fmt("invalid Notifier type: %s, must be one of: %v", cfg.Notifications, notifytypes.AllNotifierTypes)
	}
}

// getFormatter returns a new Formatter instance.
func getFormatter(notifyConfig *config.NotifyConfig, commitRangeURITemplate string) (Formatter, error) {
	switch notifyConfig.Notifications {
	case notifytypes.None:
	case notifytypes.HTMLEmail:
		return NewHTMLFormatter(commitRangeURITemplate), nil
	case notifytypes.MarkdownIssueTracker:
		return NewMarkdownFormatter(commitRangeURITemplate, notifyConfig)
	}
	return nil, nil
}

// getRegressionMetadata returns a new instance of RegressionMetadata object.
func (n *defaultNotifier) getRegressionMetadata(ctx context.Context, commit, previousCommit provider.Commit, alert *alerts.Alert, cl *clustering2.ClusterSummary, url string, frame *frame.FrameResponse) (*common.RegressionMetadata, error) {
	metadata := common.RegressionMetadata{
		RegressionCommit: commit,
		PreviousCommit:   previousCommit,
		AlertConfig:      alert,
		Cl:               cl,
		Frame:            frame,
		InstanceUrl:      url,
	}

	if alert.Algo == types.StepFitGrouping && cl.Keys != nil && len(cl.Keys) > 0 {
		// TODO(ashwinpv): If the alert config had Individual grouping, and multiple traces in the config
		// returned regressions, each of these trace will have a key in the cl.Keys array. We need to get
		// separate clusterSummaries for each regression when grouping is individual instead of treating them
		// together.
		metadata.TraceID = cl.Keys[0]
		if n.traceStore != nil && n.fs != nil {
			// Retrieve the links for the current commit.
			regressionCommitLinks, err := n.getLinksForCommit(ctx, metadata.TraceID, commit.CommitNumber)
			if err != nil {
				return nil, err
			}
			metadata.RegressionCommitLinks = regressionCommitLinks

			// Retrieve the links for the previous commit.
			prevCommitLinks, err := n.getLinksForCommit(ctx, metadata.TraceID, previousCommit.CommitNumber)
			if err != nil {
				return nil, err
			}
			metadata.PreviousCommitLinks = prevCommitLinks
		}
	}

	return &metadata, nil
}

// getLinksForCommit returns a map of the links for the given trace at the given commit number.
func (n *defaultNotifier) getLinksForCommit(ctx context.Context, traceID string, commitNumber types.CommitNumber) (map[string]string, error) {
	name, err := n.traceStore.GetSource(ctx, commitNumber, traceID)
	if err != nil {
		return nil, err
	}

	reader, err := n.fs.Open(name)
	if err != nil {
		return nil, err
	}
	defer util.Close(reader)
	formattedData, err := format.Parse(reader)
	if err != nil {
		return nil, err
	}

	return formattedData.GetLinksForMeasurement(traceID), nil
}
