package release

import (
	"slices"
	"time"

	"github.com/tidbcloud/devops/entity/github"
)

type (
	ReleaseType       string // @name release.ReleaseType
	ReleaseStatus     string // @name release.ReleaseStatus
	ReleaseTicketType string // @name release.ReleaseTicketType
)

// Enums
// Update value list `XXXValues` when update a enum
const (
	ReleaseTypePeriodic ReleaseType = "periodic"

	ReleaseStatusBeforeRelease ReleaseStatus = "before_release"
	ReleaseStatusOpen          ReleaseStatus = "open"
	ReleaseStatusFinished      ReleaseStatus = "finished"

	ReleaseTicketTypeDM ReleaseTicketType = "dm"

	// ONLY define status that we used
	// **MUST** respect the Jira and Ones workflow
	ReleaseTicketStatusTODO     = "TODO"
	ReleaseTicketStatusInDev    = "In Dev"
	ReleaseTicketStatusReady    = "READY FOR RELEASE"
	ReleaseTicketStatusDone     = "Done"
	ReleaseTicketStatusCanceled = "CANCELED"
)

var (
	ReleaseTypeValues   = []ReleaseType{ReleaseTypePeriodic}
	ReleaseStatusValues = []ReleaseStatus{
		ReleaseStatusBeforeRelease, ReleaseStatusOpen, ReleaseStatusFinished,
	}
)

type ReleaseTicketInRepo struct {
	Name              string              `json:"name"`
	Summary           string              `json:"summary"`
	Status            string              `json:"status"`
	Type              ReleaseTicketType   `json:"type"`
	AssigneeEmail     string              `json:"assignee_email"` // empty string means unassigned
	ReleaseID         uint64              `json:"release_id"`
	ReleaseName       *string             `json:"release_name"`
	GithubPRLocations []github.PRLocation `json:"github_pr_locations"`
}

type ReleaseTicket struct {
	ReleaseTicketInRepo `json:",inline"`

	GithubPRs []*github.PullRequest `json:"github_prs"`
} // @name release.ReleaseTicket

type ReleaseInRepo struct {
	ID uint64 `json:"id"` // release id in repo

	Name          string        `json:"name"` // ex: release-20230501
	Type          ReleaseType   `json:"type"`
	WindowStartAt time.Time     `json:"window_start_at"`
	WindowEndAt   time.Time     `json:"window_end_at"`
	ClosedAt      *time.Time    `json:"closed_at"`
	Status        ReleaseStatus `json:"status"`
}

type Release struct {
	ReleaseInRepo `json:",inline"`

	Tickets []*ReleaseTicket `json:"tickets"`
} // @name release.Release

func (r Release) AllTicketsIn(status ...string) bool {
	for _, ticket := range r.Tickets {
		if slices.Index(status, ticket.Status) == -1 {
			return false
		}
	}
	return true
}

// SprintWindow returns the start and end time of the sprint.
// Now it is the first day of release window.
func (r Release) SprintWindow() (time.Time, time.Time) {
	return r.WindowStartAt, r.WindowStartAt.Add(24 * time.Hour)
}
