package action

import (
	"bytes"
	"context"
	"fmt"
	"text/template"

	"github.com/tidbcloud/jiraport/pkg/clients/clinic"
	"github.com/tidbcloud/jiraport/pkg/entity"
	"github.com/tidbcloud/jiraport/pkg/matcher"

	"github.com/spf13/viper"
)

type ReportCommand struct {
	clinicClient clinic.Interface
}

func newReportCommand(clinicClient clinic.Interface) (*ReportCommand, error) {
	return &ReportCommand{clinicClient: clinicClient}, nil
}

func (cmd *ReportCommand) Exec(ctx context.Context,
	actionExecInfo *entity.NotificationActionExecInfo,
	args ...string,
) (bool, string, error) {
	// get the tenant id and cluster id.
	var tenantID string
	var clusterID string
	parseExtractor := func(e string) (*template.Template, error) {
		tmpl := template.New("").Option("missingkey=zero").Funcs(matcher.CommonFuncs)
		tmpl, err := tmpl.Parse(e)
		if err != nil {
			return nil, fmt.Errorf("parse error in %#v, %w", e, err)
		}
		return tmpl, nil
	}
	tenantExtractor, err := parseExtractor(viper.GetString("tenant-extractor"))
	if err == nil {
		var buf bytes.Buffer
		err := tenantExtractor.Execute(&buf, actionExecInfo.Notification.Issue)
		if err == nil {
			tenantID = buf.String()
		}
	}
	clusterExtractor, err := parseExtractor(viper.GetString("cluster-extractor"))
	if err == nil {
		var buf bytes.Buffer
		err := clusterExtractor.Execute(&buf, actionExecInfo.Notification.Issue)
		if err == nil {
			tenantID = buf.String()
		}
	}
	if (tenantID == "" || tenantID == `<no value>`) && clusterID != "" {
		tenantID, err = cmd.clinicClient.GetTenantIDByTenantIDAndClusterID(tenantID, clusterID)
		if err != nil {
			return false, "", err
		}
	}
	if tenantID == "" || clusterID == "" {
		return false, "", fmt.Errorf("cluster id or tenant id is empty")
	}

	// get the org id by tenant id.
	orgID, err := cmd.clinicClient.GetClinicOrgID(tenantID)
	if err != nil {
		return false, "", err
	}

	reportID, err := cmd.clinicClient.GenerateReport(orgID, clusterID)
	if err != nil {
		return false, "", fmt.Errorf("fail to generate report")
	}

	reportAddr := fmt.Sprintf(
		"%s/portal/#/orgs/%s/clusters/%s/report/1/%s",
		viper.GetString("clinic-addr"),
		orgID,
		clusterID,
		reportID)
	return true, "report address: " + reportAddr, nil

}
