// 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 bisect

import (
	"encoding/json"
	"fmt"
	"iter"
	"time"

	"golang.org/x/oscar/internal/storage"
	"golang.org/x/oscar/internal/storage/timed"
	"rsc.io/ordered"
)

// Status is the status of the bisection task.
type Status int

const (
	// Bisection task is ready to start.
	StatusReady Status = iota
	// Bisection task is enqueued.
	StatusQueued
	// Bisection task is in progress.
	StatusStarted
	// Bisection task failed.
	StatusFailed
	// Bisection task finished successfully.
	StatusSucceeded
)

// Task contains metadata and progress information
// on bisection run that is saved to the database
// and also used as a Cloud Task queue entry.
type Task struct {
	// ID is the unique identifier for the task.
	ID string
	// Trigger identifies what triggered the
	// bisection task. For instance, it can be
	// the URL of a GitHub comment requesting
	// a bisection.
	Trigger string
	// Issue identifies the problem associated
	// with the bisection. For instance, Issue
	// can be the URL of a GitHub issue for which
	// the bisection is ran.
	Issue string
	// Repository is the git repo on which the
	// bisection is performed.
	Repository string
	// Bad is the commit hash or tag
	// from which the bisection starts.
	Bad string
	// Good is the commit hash or tag
	// at which the bisection ends.
	Good string
	// Regression is Go code reproducing a
	// bug that needs to be bisected. Currently,
	// it is expected to be a Go test.
	Regression string
	// Output is the output of bisection. It
	// can contain progress and debug messages.
	Output string
	// Commit is the hash of the commit found
	// by git bisect.
	Commit string
	// Error is a message describing bisection
	// failure, if any.
	Error string
	// Status is the status of the bisection.
	Status Status
	// Updated is the last time the bisection
	// task data was updated. Together with
	// Status, Updated can be used to infer
	// when the task finished.
	Updated time.Time
	// Created is the time the bisection task
	// was created and queued for execution.
	Created time.Time
}

// Name of a task is its issue combined with ID.
func (t *Task) Name() string {
	return fmt.Sprintf("%s-%s", t.Issue, t.ID)
}

// Path is always "bisect". This is the gaby
// endpoint to which the task data will be sent.
func (t *Task) Path() string {
	return "bisect"
}

// Params encodes task ID.
func (t *Task) Params() string {
	return "id=" + t.ID
}

// A Request for bisection.
type Request struct {
	// Trigger identifies what triggered the
	// request. For instance, it can be the URL
	// of a GitHub comment requesting a bisection.
	Trigger string
	// Issue identifies the problem associated
	// with the request. For instance, Issue
	// can be the URL of a GitHub issue for which
	// the bisection is requested.
	Issue string
	// Fail is the commit hash or tag at which
	// the bisection regression occurs.
	Fail string
	// Pass is the commit hash or tag at which
	// the bisection regression does not occur.
	Pass string
	// Body is the regression as a Go program.
	Body string
	// Repo is the git repository to which the
	// regression applies.
	Repo string
}

// BisectionTasks returns an iterator over the bisection tasks.
// The first iterator value is the task ID and the other value
// is the task itself.
func (c *Client) BisectionTasks() iter.Seq2[string, *Task] {
	return func(yield func(string, *Task) bool) {
		for key, fn := range c.db.Scan(o(taskKind), o(taskKind, ordered.Inf)) {
			var id string
			if err := ordered.Decode(key, nil, &id); err != nil {
				c.db.Panic("bisect client task decode", "key", storage.Fmt(key), "err", err)
			}
			var t Task
			if err := json.Unmarshal(fn(), &t); err != nil {
				c.db.Panic("bisect client task unmarshal", "key", storage.Fmt(key), "err", err)
			}
			if !yield(id, &t) {
				return
			}
		}
	}
}

// TaskWatcher returns a new [timed.Watcher] with the given name.
// It picks up where any previous Watcher of the same name left off.
func (c *Client) TaskWatcher(name string) *timed.Watcher[*TaskEvent] {
	return timed.NewWatcher(c.slog, c.db, name, taskUpdateKind, c.decodeTaskEvent)
}

// decodeTaskEvent decodes a taskUpdateKind [timed.Entry] into
// a task event.
func (c *Client) decodeTaskEvent(t *timed.Entry) *TaskEvent {
	te := TaskEvent{
		DBTime: t.ModTime,
	}
	if err := ordered.Decode(t.Key, &te.ID); err != nil {
		c.db.Panic("bisect task event decode", "key", storage.Fmt(t.Key), "err", err)
	}
	return &te
}

// A TaskEvent is a bisection [Task]
// event returned by bisection watchers.
type TaskEvent struct {
	DBTime timed.DBTime // when event was created
	ID     string       // ID of the bisection task
}
