package jira

import (
	"context"
	"fmt"
	"strconv"
	"strings"
	"time"

	jiraentity "github.com/tidbcloud/devops/entity/jira"
	"github.com/tidbcloud/devops/pkg/infra/clients/jiracli"
	jirasvcapi "github.com/tidbcloud/devops/pkg/service/jira/api"
)

func (s *svc) ListAlerts(ctx context.Context, param jirasvcapi.ListAlertsParam) (*jirasvcapi.ListAlertsResult, error) {
	jql := fmt.Sprintf("project = %s AND issuetype = task AND \"Cluster ID\" ~ \"%d\"", s.conf.JiraProject, param.Filter.ClusterID)
	if param.Filter.Recovered != nil {
		if *param.Filter.Recovered {
			jql = fmt.Sprintf("%s AND \"Auto Recovered\" ~ \"YES\"", jql)
		} else {
			jql = fmt.Sprintf("%s AND \"Auto Recovered\" is empty", jql)
		}
	}
	if param.Filter.Type == "external" {
		jql = fmt.Sprintf("%s AND description ~ \"visibility = external\"", jql)
	} else {
		jql = fmt.Sprintf("%s AND description !~ \"visibility = external\"", jql)
	}
	if len(param.Filter.Priority) > 0 {
		jql = fmt.Sprintf("%s AND priority in (%s)", jql, strings.Join(param.Filter.Priority, ","))
	} else {
		jql = fmt.Sprintf("%s AND priority in (Major,Critical)", jql)
	}
	if len(param.Search) > 0 {
		jql = fmt.Sprintf("%s AND summary ~ \"%s\"", jql, param.Search)
	}
	jql = fmt.Sprintf("%s AND created >= %s AND created <= %s", jql,
		time.Unix(param.Filter.StartTs, 0).Format("2006-01-02"),
		time.Unix(param.Filter.EndTs, 0).AddDate(0, 0, 1).Format("2006-01-02"))
	jql = fmt.Sprintf("%s ORDER BY created DESC, priority DESC, updated DESC", jql)

	opts := &jiracli.SearchOptions{
		NextPageToken: param.PageToken,
		MaxResults:    param.PageSize,
		Fields:        []string{"summary", "priority", "created", "updated", "customfield_10910"},
	}
	result, err := s.jiraClient.SearchIssues(ctx, jql, opts)
	if err != nil {
		return nil, err
	}

	alerts := make([]*jiraentity.Alert, 0, len(result.Issues))
	for _, issue := range result.Issues {
		recovered := false
		if v, ok := issue.Fields.Unknowns["customfield_10910"]; ok && v != nil {
			recovered = true
		}
		alert := &jiraentity.Alert{
			Key:       issue.Key,
			Name:      issue.Fields.Summary,
			Priority:  issue.Fields.Priority.Name,
			Recovered: recovered,
			CreatedAt: time.Time(issue.Fields.Created).Unix(),
			UpdatedAt: time.Time(issue.Fields.Updated).Unix(),
		}
		alerts = append(alerts, alert)
	}

	return &jirasvcapi.ListAlertsResult{
		Alerts:        alerts,
		IsLast:        result.IsLast,
		NextPageToken: result.NextPageToken,
	}, nil
}

func (s *svc) GetAlertSummary(ctx context.Context, param jirasvcapi.GetAlertsSummaryParam) (*jiraentity.AlertSummary, error) {
	rdb := s.db.ReadDB(ctx)

	var data []jiraentity.SeriesTrend
	sql := fmt.Sprintf(`
				SELECT
					name,
					summary AS series,
					value
				FROM (
					SELECT
						DATE_FORMAT(created_time, '%%Y-%%m') AS name,
						summary,
						COUNT(1) AS value,
						ROW_NUMBER() OVER w AS row_num
					FROM jirainterval.jira_issueview
					WHERE project_id in (10415,10422,10048)
					  AND issue_type = 'Task'
					  AND cluster_id = %s
					  AND created_time BETWEEN FROM_UNIXTIME(%d) AND FROM_UNIXTIME(%d)
					group by DATE_FORMAT(created_time, '%%Y-%%m'), summary
					WINDOW w AS (PARTITION BY DATE_FORMAT(created_time, '%%Y-%%m') ORDER BY count(1) DESC)
					ORDER BY name, value DESC
				) AS ranked_data
				WHERE row_num <= 5
				ORDER BY name, value DESC;
			`, strconv.FormatUint(param.ClusterID, 10), param.StartTs, param.EndTs)
	err := rdb.Raw(sql).Scan(&data).Error
	if err != nil {
		return nil, fmt.Errorf("get alert summary top alert failed: %w", err)
	}
	return &jiraentity.AlertSummary{
		Trends: data,
	}, nil
}
