package status

import (
	"bytes"
	"context"
	"encoding/gob"
	"sync"

	"cloud.google.com/go/datastore"
	"go.skia.org/infra/go/autoroll"
	"go.skia.org/infra/go/ds"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
)

// AutoRollStatus is a struct which provides roll-up status information about
// the AutoRoll Bot.
type AutoRollStatus struct {
	AutoRollMiniStatus
	ChildHead       string                    `json:"childHead"`
	ChildName       string                    `json:"childName"`
	CurrentRoll     *autoroll.AutoRollIssue   `json:"currentRoll"`
	Error           string                    `json:"error"`
	FullHistoryUrl  string                    `json:"fullHistoryUrl"`
	IssueUrlBase    string                    `json:"issueUrlBase"`
	LastRoll        *autoroll.AutoRollIssue   `json:"lastRoll"`
	LastRollRev     string                    `json:"lastRollRev"`
	ParentName      string                    `json:"parentName"`
	Recent          []*autoroll.AutoRollIssue `json:"recent"`
	Status          string                    `json:"status"`
	ThrottledUntil  int64                     `json:"throttledUntil"`
	ValidModes      []string                  `json:"validModes"`
	ValidStrategies []string                  `json:"validStrategies"`
}

// AutoRollMiniStatus is a struct which provides a minimal amount of status
// information about the AutoRoll Bot.
// TODO(borenet): Some of this duplicates things in AutoRollStatus. Revisit and
// either don't include AutoRollMiniStatus in AutoRollStatus or de-dupe the
// fields after revamping the UI.
type AutoRollMiniStatus struct {
	// Revision of the current roll, if any.
	CurrentRollRev string `json:"currentRollRev"`

	// Revision of the last successful roll.
	LastRollRev string `json:"lastRollRev"`

	// The number of failed rolls since the last successful roll.
	NumFailedRolls int `json:"numFailed"`

	// The number of commits which have not been rolled.
	NumNotRolledCommits int `json:"numBehind"`
}

// Fake ancestor we supply for all AutoRollStatus, to force strong consistency.
// We lose some performance this way but it keeps our tests from flaking.
func fakeAncestor() *datastore.Key {
	rv := ds.NewKey(ds.KIND_AUTOROLL_STATUS_ANCESTOR)
	rv.ID = 13 // Bogus ID.
	return rv
}

// DsStatusWrapper is a helper struct used for storing an AutoRollStatus in the
// datastore.
type DsStatusWrapper struct {
	Data   []byte `datastore:"data,noindex"`
	Roller string `datastore:"roller"`
}

// Create a key for the given roller.
func key(rollerName string) *datastore.Key {
	key := ds.NewKey(ds.KIND_AUTOROLL_STATUS)
	key.Name = rollerName
	key.Parent = fakeAncestor()
	return key
}

// Set the AutoRollStatus for the given roller in the datastore. Should only
// be called by the roller itself.
func Set(ctx context.Context, rollerName string, st *AutoRollStatus) error {
	buf := bytes.NewBuffer(nil)
	if err := gob.NewEncoder(buf).Encode(st); err != nil {
		return err
	}
	w := &DsStatusWrapper{
		Data:   buf.Bytes(),
		Roller: rollerName,
	}
	_, err := ds.DS.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
		_, err := tx.Put(key(rollerName), w)
		return err
	})
	return err
}

// Get the AutoRollStatus for the given roller from the datastore. Most callers
// should use AutoRollStatusCache.
func Get(ctx context.Context, rollerName string) (*AutoRollStatus, error) {
	var w DsStatusWrapper
	if err := ds.DS.Get(ctx, key(rollerName), &w); err != nil {
		return nil, err
	}
	rv := new(AutoRollStatus)
	if err := gob.NewDecoder(bytes.NewReader(w.Data)).Decode(rv); err != nil {
		return nil, err
	}
	return rv, nil
}

// AutoRollStatusCache is a struct used for caching roll-up status
// information about the AutoRoll Bot.
type AutoRollStatusCache struct {
	mtx    sync.RWMutex
	roller string
	status *AutoRollStatus
}

// NewCache returns an AutoRollStatusCache instance.
func NewCache(ctx context.Context, rollerName string) (*AutoRollStatusCache, error) {
	c := &AutoRollStatusCache{
		roller: rollerName,
	}
	if err := c.Update(ctx); err != nil {
		return nil, err
	}
	return c, nil
}

// Return the AutoRollStatus as of the last call to Update().
func (c *AutoRollStatusCache) Get() *AutoRollStatus {
	c.mtx.RLock()
	defer c.mtx.RUnlock()
	return c.status.Copy()
}

func (s *AutoRollStatus) Copy() *AutoRollStatus {
	if s == nil {
		sklog.Warningf("Copying nil AutoRollStatus.")
		return nil
	}
	var recent []*autoroll.AutoRollIssue
	if s.Recent != nil {
		recent = make([]*autoroll.AutoRollIssue, 0, len(s.Recent))
		for _, r := range s.Recent {
			recent = append(recent, r.Copy())
		}
	}
	rv := &AutoRollStatus{
		AutoRollMiniStatus: AutoRollMiniStatus{
			CurrentRollRev:      s.CurrentRollRev,
			LastRollRev:         s.LastRollRev,
			NumFailedRolls:      s.NumFailedRolls,
			NumNotRolledCommits: s.NumNotRolledCommits,
		},
		ChildHead:       s.ChildHead,
		ChildName:       s.ChildName,
		Error:           s.Error,
		FullHistoryUrl:  s.FullHistoryUrl,
		IssueUrlBase:    s.IssueUrlBase,
		LastRollRev:     s.LastRollRev,
		ParentName:      s.ParentName,
		Recent:          recent,
		Status:          s.Status,
		ThrottledUntil:  s.ThrottledUntil,
		ValidModes:      util.CopyStringSlice(s.ValidModes),
		ValidStrategies: util.CopyStringSlice(s.ValidStrategies),
	}
	if s.CurrentRoll != nil {
		rv.CurrentRoll = s.CurrentRoll.Copy()
	}
	if s.LastRoll != nil {
		rv.LastRoll = s.LastRoll.Copy()
	}
	return rv
}

// Return the AutoRollMiniStatus as of the last call to Update().
func (c *AutoRollStatusCache) GetMini() *AutoRollMiniStatus {
	return &c.Get().AutoRollMiniStatus
}

// Update updates the current status information.
func (c *AutoRollStatusCache) Update(ctx context.Context) error {
	status, err := Get(ctx, c.roller)
	if err == datastore.ErrNoSuchEntity || status == nil {
		// This will occur the first time the roller starts,
		// before it sets the status for the first time. Ignore.
		sklog.Warningf("Unable to find AutoRollStatus for %s. Is this the first startup for this roller?", c.roller)
		status = &AutoRollStatus{}
	} else if err != nil {
		return err
	}
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.status = status
	return nil
}
