// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gerrit

import (
	"cmp"
	"encoding/json"
	"fmt"
	"slices"
	"strings"
	"time"
)

// A Change holds information for a single Gerrit change.
// This internally holds JSON encoded data,
// and only decodes what is needed.
type Change struct {
	num  int
	data []byte
}

// ChangeInfo returns a [ChangeInfo] holding almost all the information
// about a [Change]. This does not include the file comments,
// which can be retrieved using the [Client.Comments] method.
func (c *Client) ChangeInfo(ch *Change) *ChangeInfo {
	var ci ChangeInfo
	c.unmarshal(ch, "change", &ci)
	return &ci
}

// ChangeNumber returns the Gerrit change number.
// This is unique for a given Gerrit instance.
func (c *Client) ChangeNumber(ch *Change) int {
	return ch.num
}

// Project returns the project that the change is in.
func (c *Client) ChangeProject(ch *Change) string {
	var project struct {
		Project string `json:"project"`
	}
	c.unmarshal(ch, "project", &project)
	return project.Project
}

// Status returns the status of the change: NEW, MERGED, ABANDONED.
func (c *Client) ChangeStatus(ch *Change) string {
	var status struct {
		Status string `json:"status"`
	}
	c.unmarshal(ch, "status", &status)
	return status.Status
}

// ChangeOwner returns the owner of the Gerrit change: the account that
// created the change.
func (c *Client) ChangeOwner(ch *Change) *AccountInfo {
	var owner struct {
		Owner json.RawMessage `json:"owner"`
	}
	c.unmarshal(ch, "owner", &owner)
	return c.loadAccount(owner.Owner)
}

// ChangeSubmitter returns the account that submitted the change.
// If the change has not been submitted this returns nil.
func (c *Client) ChangeSubmitter(ch *Change) *AccountInfo {
	var submitter struct {
		Submitter json.RawMessage `json:"submitter"`
	}
	c.unmarshal(ch, "submitter", &submitter)

	if len(submitter.Submitter) == 0 {
		return nil
	}
	return c.loadAccount(submitter.Submitter)
}

// ChangeTimes holds relevant times for a [Change].
type ChangeTimes struct {
	Created   time.Time // when change was created
	Updated   time.Time // when change was updated, zero if never
	Submitted time.Time // when change was submitted, zero if not
	Abandoned time.Time // when change was abandoned, zero if not
}

// ChangeTimes returns the created, updated, submitted, and abandoned times
// for a change. If the change is not submitted or not abandoned,
// those times will be zero.
func (c *Client) ChangeTimes(ch *Change) ChangeTimes {
	var times struct {
		Created   TimeStamp `json:"created"`
		Updated   TimeStamp `json:"updated"`
		Submitted TimeStamp `json:"submitted"`
		Status    string    `json:"status"`
	}
	c.unmarshal(ch, "times", &times)
	created := times.Created.Time()
	updated := times.Updated.Time()
	submitted := times.Submitted.Time()

	var abandoned time.Time
	if times.Status == "ABANDONED" {
		type message struct {
			Date    TimeStamp `json:"date"`
			Message string    `json:"message"`
		}
		var messages struct {
			Messages []message `json:"messages"`
		}
		c.unmarshal(ch, "abandoned messages", &messages)
		for _, msg := range slices.Backward(messages.Messages) {
			if strings.HasPrefix(msg.Message, "Abandoned") {
				abandoned = msg.Date.Time()
				break
			}
		}
		if abandoned.IsZero() {
			c.slog.Error("gerrit change abandoned missing message", "num", ch.num, "data", ch.data)
			c.db.Panic("gerrit change abandoned missing message", "num", ch.num)
		}
	}

	return ChangeTimes{
		Created:   created,
		Updated:   updated,
		Submitted: submitted,
		Abandoned: abandoned,
	}
}

// ChangeSubject returns the subject of a [Change].
// This is the first line of the change description.
func (c *Client) ChangeSubject(ch *Change) string {
	var subject struct {
		Subject string `json:"subject"`
	}
	c.unmarshal(ch, "subject", &subject)
	return subject.Subject
}

// ChangeMessages returns the messages on a [Change].
// These are the top-level messages created by clicking on
// the top REPLY button when reviewing a change.
// Inline file comments are returned by [Client.Comments].
func (c *Client) ChangeMessages(ch *Change) []*ChangeMessageInfo {
	var messages struct {
		Messages []json.RawMessage `json:"messages"`
	}
	c.unmarshal(ch, "messages", &messages)

	// Unpack into a changeMessageInfo struct, and then convert to
	// ChangeMessageInfo, so that we don't have to unpack the lengthy
	// AccountInfo data each time.
	type changeMessageInfo struct {
		ID                string            `json:"id"`
		Author            json.RawMessage   `json:"author,omitempty"`
		RealAuthor        json.RawMessage   `json:"real_author,omitempty"`
		Date              TimeStamp         `json:"date"`
		Message           string            `json:"message"`
		AccountsInMessage []json.RawMessage `json:"accounts_in_message,omitempty"`
		Tag               string            `json:"tag,omitempty"`
		RevisionNumber    int               `json:"_revision_number,omitempty"`
	}

	ret := make([]*ChangeMessageInfo, 0, len(messages.Messages))
	for _, msg := range messages.Messages {
		var cmi changeMessageInfo
		if err := json.Unmarshal(msg, &cmi); err != nil {
			c.slog.Error("gerrit message decode failure", "num", ch.num, "data", msg, "err", err)
			c.db.Panic("gerrit message decode failure", "num", ch.num, "err", err)
		}

		var aims []*AccountInfo
		for _, aim := range cmi.AccountsInMessage {
			aims = append(aims, c.loadAccount(aim))
		}
		r := &ChangeMessageInfo{
			ID:                cmi.ID,
			Author:            c.loadAccount(cmi.Author),
			RealAuthor:        c.loadAccount(cmi.RealAuthor),
			Date:              cmi.Date,
			Message:           cmi.Message,
			AccountsInMessage: aims,
			Tag:               cmi.Tag,
			RevisionNumber:    cmi.RevisionNumber,
		}
		ret = append(ret, r)
	}

	return ret
}

// ChangeDescription returns the current description of the change.
func (c *Client) ChangeDescription(ch *Change) string {
	type commitInfo struct {
		Message string `json:"message"`
	}
	type revisionInfo struct {
		Commit commitInfo `json:"commit"`
	}
	var revisions struct {
		CurrentRevision string                  `json:"current_revision"`
		Revisions       map[string]revisionInfo `json:"revisions"`
	}
	c.unmarshal(ch, "current revision", &revisions)

	rev, ok := revisions.Revisions[revisions.CurrentRevision]
	if !ok {
		c.slog.Error("gerrit no revision data for current revision", "num", ch.num, "data", ch.data, "currentRevision", revisions.CurrentRevision)
		c.db.Panic("gerrit no revision data for current revision", "num", ch.num)
	}

	return rev.Commit.Message
}

// ChangeWorkInProgress reports whether the change is marked as
// work-in-progress.
func (c *Client) ChangeWorkInProgress(ch *Change) bool {
	var workInProgress struct {
		WorkInProgress bool `json:"work_in_progress"`
	}
	c.unmarshal(ch, "work in progress", &workInProgress)
	return workInProgress.WorkInProgress
}

// ChangeReviewers returns a list of accounts that are listed as
// reviewers of this change.
// Note that this is not identical to ChangeInfo.Reviewers,
// which includes both reviewers and people CC'ed.
func (c *Client) ChangeReviewers(ch *Change) []*AccountInfo {
	var reviewers struct {
		Reviewers map[string][]json.RawMessage `json:"reviewers"`
	}
	c.unmarshal(ch, "reviewed", &reviewers)

	revs := reviewers.Reviewers["REVIEWER"]
	if len(revs) == 0 {
		return nil
	}

	ret := make([]*AccountInfo, 0, len(revs))
	for _, rev := range revs {
		ret = append(ret, c.loadAccount(rev))
	}
	return ret
}

// ChangeLabels returns a map from label names to LabelInfo values.
func (c *Client) ChangeLabels(ch *Change) map[string]*LabelInfo {
	var labels struct {
		Labels map[string]json.RawMessage `json:"labels"`
	}
	c.unmarshal(ch, "labels", &labels)

	ret := make(map[string]*LabelInfo, len(labels.Labels))
	for name, msg := range labels.Labels {
		ret[name] = c.unmarshalLabel(ch, msg)
	}
	return ret
}

// ChangeLabel returns information about a label.
// It returns nil if that label is not present.
func (c *Client) ChangeLabel(ch *Change, label string) *LabelInfo {
	var labels struct {
		Labels map[string]json.RawMessage `json:"labels"`
	}
	c.unmarshal(ch, "labels", &labels)
	msg, ok := labels.Labels[label]
	if !ok {
		return nil
	}
	return c.unmarshalLabel(ch, msg)
}

// unmarshalLabel unmarshals a LabelInfo.
func (c *Client) unmarshalLabel(ch *Change, input json.RawMessage) *LabelInfo {
	// Unpack into approvalInfo and labelInfo structs, and then convert to
	// ApprovalInfo and LabelInfo, so that we don't have to unpack the
	// lengthy AccountInfo data each time.
	type approvalInfo struct {
		Value                int             `json:"value,omitempty"`
		PermittedVotingRange VotingRangeInfo `json:"permitted_voting_range,omitempty"`
		Date                 TimeStamp       `json:"date,omitempty"`
		Tag                  string          `json:"tag,omitempty"`
		PostSubmit           bool            `json:"post_submit,omitempty"`
	}
	type labelInfo struct {
		Optional     bool              `json:"optional,omitempty"`
		Description  string            `json:"description,omitempty"`
		Approved     json.RawMessage   `json:"approved,omitempty"`
		Rejected     json.RawMessage   `json:"rejected,omitempty"`
		Recommended  json.RawMessage   `json:"recommended,omitempty"`
		Disliked     json.RawMessage   `json:"disliked,omitempty"`
		Blocking     bool              `json:"blocking,omitempty"`
		Value        int               `json:"value,omitempty"`
		DefaultValue int               `json:"default_value,omitempty"`
		Votes        []int             `json:"votes,omitempty"`
		All          []json.RawMessage `json:"all,omitempty"`
		Values       map[string]string `json:"values,omitempty"`
	}

	var li labelInfo
	if err := json.Unmarshal(input, &li); err != nil {
		c.slog.Error("gerrit label info decode failure", "num", ch.num, "data", ch.data, "err", err)
		c.db.Panic("gerrit label info decode failure", "num", ch.num, "err", err)
	}

	all := make([]*ApprovalInfo, 0, len(li.All))
	for _, aai := range li.All {
		ac := c.loadAccount(aai)
		var jai approvalInfo
		if err := json.Unmarshal(aai, &jai); err != nil {
			c.slog.Error("gerrit label approval decode failure", "num", ch.num, "data", ch.data, "err", err)
			c.db.Panic("gerrit label approval decode failure", "num", ch.num, "err", err)
		}
		bai := &ApprovalInfo{
			AccountInfo:          ac,
			Value:                jai.Value,
			PermittedVotingRange: jai.PermittedVotingRange,
			Date:                 jai.Date,
			Tag:                  jai.Tag,
			PostSubmit:           jai.PostSubmit,
		}
		all = append(all, bai)
	}

	return &LabelInfo{
		Optional:     li.Optional,
		Description:  li.Description,
		Approved:     c.loadAccount(li.Approved),
		Rejected:     c.loadAccount(li.Rejected),
		Recommended:  c.loadAccount(li.Recommended),
		Disliked:     c.loadAccount(li.Disliked),
		Blocking:     li.Blocking,
		Value:        li.Value,
		DefaultValue: li.DefaultValue,
		Votes:        li.Votes,
		All:          all,
		Values:       li.Values,
	}
}

// ChangeCommitAuthor returns the author of a given patch set number
// of a change. If the patch set number does not exist or the information
// is missing, this returns nil.
func (c *Client) ChangeCommitAuthor(ch *Change, patchset int) *GitPersonInfo {
	var revisions struct {
		Revisions map[string]json.RawMessage `json:"revisions"`
	}
	c.unmarshal(ch, "revisions", &revisions)
	for _, rev := range revisions.Revisions {
		var number struct {
			Number int `json:"_number"`
		}
		if err := json.Unmarshal(rev, &number); err != nil {
			c.slog.Error("gerrit revision number decode failure", "num", ch.num, "data", ch.data, "err", err)
			c.db.Panic("gerrit revision number decode failure", "num", ch.num, "err", err)
		}
		if number.Number != patchset {
			continue
		}

		type commitInfo struct {
			Author *GitPersonInfo `json:"author"`
		}
		var commit struct {
			Commit *commitInfo `json:"commit"`
		}
		if err := json.Unmarshal(rev, &commit); err != nil {
			c.slog.Error("gerrit revision commit decode failure", "num", ch.num, "data", ch.data, "err", err)
			c.db.Panic("gerrit revision commit decode failure", "num", ch.num, "err", err)
		}
		if commit.Commit == nil {
			return nil
		}
		return commit.Commit.Author
	}
	return nil
}

// ChangeHashTags returns the list of hashtags set on the change.
func (c *Client) ChangeHashtags(ch *Change) []string {
	var hashtags struct {
		Hashtags []string `json:"hashtags"`
	}
	c.unmarshal(ch, "hashtags", &hashtags)
	return hashtags.Hashtags
}

// ChangeCommentCounts returns the total number of comments and the
// nmber of unresolved comments.
func (c *Client) ChangeCommentCounts(ch *Change) (total, unresolved int) {
	var counts struct {
		TotalCommentCount      int `json:"total_comment_count"`
		UnresolvedCommentCount int `json:"unresolved_comment_count"`
	}
	c.unmarshal(ch, "comment counts", &counts)
	return counts.TotalCommentCount, counts.UnresolvedCommentCount
}

// ChangeRevisions returns information about all the patch sets,
// ordered by patch set number.
func (c *Client) ChangeRevisions(ch *Change) []*RevisionInfo {
	// Unpack into commitInfo and revisionInfo structs,
	// and then convert to CommitInfo and RevisionInfo,
	// so that we don't have to unpack the lengthy AccountInfo
	// data each time. We also skip some CommitInfo fields.
	type commitInfo struct {
		Commit    string         `json:"commit,omitempty"`
		Author    *GitPersonInfo `json:"author,omitempty"`
		Committer *GitPersonInfo `json:"committer,omitempty"`
		Subject   string         `json:"subject"`
		Message   string         `json:"message,omitempty"`
	}
	type revisionInfo struct {
		Kind         string          `json:"kind"`
		Number       int             `json:"_number"`
		Created      TimeStamp       `json:"created"`
		Uploader     json.RawMessage `json:"uploader"`
		RealUploader json.RawMessage `json:"real_uploader,omitempty"`
		Ref          string          `json:"ref"`
		Commit       *commitInfo     `json:"commit,omitempty"`
		Branch       string          `json:"branch,omitempty"`
		Description  string          `json:"description,omitempty"`
	}
	var revisions struct {
		Revisions map[string]*revisionInfo `json:"revisions"`
	}
	c.unmarshal(ch, "revisions", &revisions)

	toCommitInfo := func(from *commitInfo) *CommitInfo {
		if from == nil {
			return nil
		}
		return &CommitInfo{
			Commit:    from.Commit,
			Author:    from.Author,
			Committer: from.Committer,
			Subject:   from.Subject,
			Message:   from.Message,
		}
	}

	revs := make([]*RevisionInfo, 0, len(revisions.Revisions))
	for _, rev := range revisions.Revisions {
		ri := &RevisionInfo{
			Kind:         rev.Kind,
			Number:       rev.Number,
			Created:      rev.Created,
			Uploader:     c.loadAccount(rev.Uploader),
			RealUploader: c.loadAccount(rev.RealUploader),
			Ref:          rev.Ref,
			Commit:       toCommitInfo(rev.Commit),
			Branch:       rev.Branch,
			Description:  rev.Description,
		}
		revs = append(revs, ri)
	}

	slices.SortFunc(revs, func(a, b *RevisionInfo) int {
		return cmp.Compare(a.Number, b.Number)
	})

	return revs
}

// unmarshal unmarshals ch.data into a value. If the unmarshal fails, it
// crashes with an error.
func (c *Client) unmarshal(ch *Change, msg string, val any) {
	if err := json.Unmarshal(ch.data, val); err != nil {
		c.slog.Error(fmt.Sprintf("gerrit %s decode failure", msg), "num", ch.num, "data", ch.data, "err", err)
		c.db.Panic(fmt.Sprintf("gerrit %s decode failure", msg), "num", ch.num, "err", err)
	}
}
