package silence

import (
	"context"
	"encoding/json"
	"fmt"
	"regexp"
	"time"

	"cloud.google.com/go/datastore"
	"go.skia.org/infra/am/go/note"
	"go.skia.org/infra/go/ds"
	"go.skia.org/infra/go/human"
	"go.skia.org/infra/go/paramtools"
	"go.skia.org/infra/go/sklog"
)

const (
	SILENCE_PARENT_KEY = "-silence-"

	NUM_RECENTLY_ARCHIVED = 500
)

// Silence is a filter that matches Incidents and is used to silence them.
type Silence struct {
	Key            string              `json:"key" datastore:"-"`
	Active         bool                `json:"active" datastore:"active"`
	User           string              `json:"user" datastore:"user"`
	ParamSet       paramtools.ParamSet `json:"param_set" datastore:"-"`
	ParamSetSerial string              `json:"-" datastore:"param_set_serial,noindex"`
	Created        int64               `json:"created" datastore:"created"`
	Updated        int64               `json:"updated" datastore:"updated"`
	Duration       string              `json:"duration" datastore:"duration"`
	Notes          []note.Note         `json:"notes" datastore:"notes,flatten"`
}

// New creates a new Silence.
//
// user - Email address of the person that created the silence.
func New(user string) *Silence {
	now := time.Now().Unix()
	return &Silence{
		Active:   true,
		User:     user,
		ParamSet: paramtools.ParamSet{},
		Created:  now,
		Updated:  now,
		Duration: "2h",
		Notes:    []note.Note{},
	}
}

// Load converts the JSON paramset back into a paramset.
func (silence *Silence) Load(ps []datastore.Property) error {
	if err := datastore.LoadStruct(silence, ps); err != nil {
		return err
	}
	if err := json.Unmarshal([]byte(silence.ParamSetSerial), &silence.ParamSet); err != nil {
		return err
	}
	return nil
}

// Save serializes the paramset as JSON for storing in the Datastore.
func (silence *Silence) Save() ([]datastore.Property, error) {
	b, err := json.Marshal(silence.ParamSet)
	if err != nil {
		return nil, err
	}
	silence.ParamSetSerial = string(b)
	return datastore.SaveStruct(silence)
}

// ValidateRegexes returns an error if the silence is not valid.
func (silence *Silence) ValidateRegexes() error {
	for _, vals := range silence.ParamSet {
		for _, v := range vals {
			if _, err := regexp.Compile(fmt.Sprintf(`^%s$`, v)); err != nil {
				return err
			}
		}
	}
	return nil
}

// Store saves and updates silences in Cloud Datastore.
type Store struct {
	ds *datastore.Client
}

// NewStore creates a new Store from the given Datastore client.
func NewStore(ds *datastore.Client) *Store {
	store := &Store{
		ds: ds,
	}
	// Start a go routine that expires old silences.
	go func(store *Store) {
		for range time.Tick(15 * time.Second) {
			now := time.Now()
			silences, err := store.GetAll()
			if err != nil {
				sklog.Errorf("Silence expirer failed to retrieve silences: %s", err)
			}
			for _, s := range silences {
				d, err := human.ParseDuration(s.Duration)
				if err != nil {
					sklog.Errorf("Silence has invalid duration: %s", err)
					continue
				}
				if time.Unix(s.Created, 0).Add(d).Before(now) {
					if _, err := store.Archive(s.Key); err != nil {
						sklog.Errorf("Failed to archive expired silence: %s", err)
					}
				}
			}
		}
	}(store)
	return store
}

func (s *Store) Put(silence *Silence) (*Silence, error) {
	_, err := human.ParseDuration(silence.Duration)
	if err != nil {
		return nil, fmt.Errorf("Silence has invalid duration: %s", err)
	}

	// Key used if this is a create.
	ancestor := ds.NewKey(ds.SILENCE_ACTIVE_PARENT_AM)
	ancestor.Name = SILENCE_PARENT_KEY
	key := ds.NewKey(ds.SILENCE_AM)
	key.Parent = ancestor

	if silence.Key != "" {
		// This is an update, so use the key provided.
		var err error
		key, err = datastore.DecodeKey(silence.Key)
		if err != nil {
			return nil, err
		}
	}

	silence.Active = true

	var pendingKey *datastore.PendingKey
	commit, err := s.ds.RunInTransaction(context.Background(), func(tx *datastore.Transaction) error {
		var err error
		if pendingKey, err = tx.Put(key, silence); err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return nil, fmt.Errorf("Failed to write Silence: %s", err)
	}

	silence.Key = commit.Key(pendingKey).Encode()
	return silence, nil

}

// _mutate is a helper function for updating Silences inside a transaction.
func (s *Store) _mutate(encodedKey string, mutator func(silence *Silence) error) (*Silence, error) {
	key, err := datastore.DecodeKey(encodedKey)
	if err != nil {
		return nil, err
	}
	var silence Silence
	_, err = s.ds.RunInTransaction(context.Background(), func(tx *datastore.Transaction) error {
		if err := tx.Get(key, &silence); err != nil {
			return err
		}
		if err := mutator(&silence); err != nil {
			return err
		}
		if _, err := tx.Put(key, &silence); err != nil {
			return err
		}
		return nil
	})
	silence.Key = encodedKey
	return &silence, err
}

func (s *Store) Archive(encodedKey string) (*Silence, error) {
	return s._mutate(encodedKey, func(silence *Silence) error {
		silence.Active = false
		silence.Updated = time.Now().Unix()
		return nil
	})
}

func (s *Store) Reactivate(encodedKey, duration, user string) (*Silence, error) {
	_, err := human.ParseDuration(duration)
	if err != nil {
		return nil, fmt.Errorf("Silence has invalid duration: %s", err)
	}

	return s._mutate(encodedKey, func(silence *Silence) error {
		now := time.Now().Unix()
		silence.Active = true
		silence.Created = now
		silence.Updated = now
		silence.Duration = duration
		silence.Notes = append(silence.Notes, note.Note{
			Text:   fmt.Sprintf("Reactivated by %q.", user),
			Author: user,
			TS:     now,
		})

		return nil
	})
}

func (s *Store) Delete(encodedKey string) error {
	key, err := datastore.DecodeKey(encodedKey)
	if err != nil {
		return err
	}
	if err := s.ds.Delete(context.Background(), key); err != nil {
		return fmt.Errorf("Failed to delete Silence: %s", err)
	}

	return nil
}

func (s *Store) AddNote(encodedKey string, note note.Note) (*Silence, error) {
	return s._mutate(encodedKey, func(silence *Silence) error {
		silence.Updated = time.Now().Unix()
		silence.Notes = append(silence.Notes, note)
		return nil
	})
}

func (s *Store) DeleteNote(encodedKey string, index int) (*Silence, error) {
	return s._mutate(encodedKey, func(silence *Silence) error {
		if index < 0 || index > len(silence.Notes)-1 {
			return fmt.Errorf("Index for delete out of range.")
		}
		silence.Updated = time.Now().Unix()
		silence.Notes = append(silence.Notes[:index], silence.Notes[index+1:]...)
		return nil
	})
}

// GetAll returns a list of all active Silences.
func (s *Store) GetAll() ([]Silence, error) {
	var active []Silence
	ancestor := ds.NewKey(ds.SILENCE_ACTIVE_PARENT_AM)
	ancestor.Name = SILENCE_PARENT_KEY
	q := ds.NewQuery(ds.SILENCE_AM).Filter("active=", true).Ancestor(ancestor)
	keys, err := s.ds.GetAll(context.Background(), q, &active)
	for i, key := range keys {
		if active[i].Key == "" {
			active[i].Key = key.Encode()
		}
	}
	return active, err
}

// GetRecentlyArchived returns N most recently archived Silences that were
// updated within the specified duration. updatedWithin can be 0 if we want
// all recently archived silences.
func (s *Store) GetRecentlyArchived(updatedWithin time.Duration) ([]Silence, error) {
	var archived []Silence
	ancestor := ds.NewKey(ds.SILENCE_ACTIVE_PARENT_AM)
	ancestor.Name = SILENCE_PARENT_KEY
	modifiedAfter := int64(0)
	if updatedWithin != 0 {
		modifiedAfter = time.Now().Add(-updatedWithin).Unix()
	}
	q := ds.NewQuery(ds.SILENCE_AM).Filter("active=", false).Filter("updated>", modifiedAfter).Ancestor(ancestor).Order("-updated").Limit(NUM_RECENTLY_ARCHIVED)
	keys, err := s.ds.GetAll(context.Background(), q, &archived)
	if err != nil {
		return nil, fmt.Errorf("Failed to make query: %s", err)
	}
	for i, key := range keys {
		if archived[i].Key == "" {
			archived[i].Key = key.Encode()
		}
	}
	return archived, err
}
