// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package lro supports Long Running Operations for the Google Cloud Libraries.
//
// This package is still experimental and subject to change.
package longrunning

import (
	"context"
	"errors"
	"testing"
	"time"

	pb "cloud.google.com/go/longrunning/autogen/longrunningpb"
	gax "github.com/googleapis/gax-go/v2"
	"github.com/googleapis/gax-go/v2/apierror"
	"google.golang.org/genproto/googleapis/rpc/errdetails"
	rpcstatus "google.golang.org/genproto/googleapis/rpc/status"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/anypb"
	"google.golang.org/protobuf/types/known/durationpb"
)

type getterService struct {
	operationsClient

	// clock represents the fake current time of the service.
	// It is the running sum of the of the duration we have slept.
	clock time.Duration

	// getTimes records the times at which GetOperation is called.
	getTimes []time.Duration

	// results are the fake results that GetOperation should return.
	results []*pb.Operation
}

func (s *getterService) GetOperation(context.Context, *pb.GetOperationRequest, ...gax.CallOption) (*pb.Operation, error) {
	i := len(s.getTimes)
	s.getTimes = append(s.getTimes, s.clock)
	if i >= len(s.results) {
		return nil, errors.New("unexpected call")
	}
	return s.results[i], nil
}

func (s *getterService) sleeper() sleeper {
	return func(_ context.Context, d time.Duration) error {
		s.clock += d
		return nil
	}
}

func TestWait(t *testing.T) {
	responseDur := durationpb.New(42 * time.Second)
	responseAny, err := anypb.New(responseDur)
	if err != nil {
		t.Fatal(err)
	}

	s := &getterService{
		results: []*pb.Operation{
			{Name: "foo"},
			{Name: "foo"},
			{Name: "foo"},
			{Name: "foo"},
			{Name: "foo"},
			{
				Name: "foo",
				Done: true,
				Result: &pb.Operation_Response{
					Response: responseAny,
				},
			},
		},
	}
	op := &Operation{
		c:     s,
		proto: &pb.Operation{Name: "foo"},
	}
	if op.Done() {
		t.Fatal("operation should not have completed yet")
	}

	var resp durationpb.Duration
	bo := gax.Backoff{
		Initial: 1 * time.Second,
		Max:     3 * time.Second,
	}
	if err := op.wait(context.Background(), &resp, &bo, s.sleeper()); err != nil {
		t.Fatal(err)
	}
	if !proto.Equal(&resp, responseDur) {
		t.Errorf("response, got %v, want %v", resp, responseDur)
	}
	if !op.Done() {
		t.Errorf("operation should have completed")
	}

	maxWait := []time.Duration{
		1 * time.Second,
		2 * time.Second,
		3 * time.Second,
		3 * time.Second,
		3 * time.Second,
	}
	for i := 0; i < len(s.getTimes)-1; i++ {
		w := s.getTimes[i+1] - s.getTimes[i]
		if mw := maxWait[i]; w > mw {
			t.Errorf("backoff, waited %s, max %s", w, mw)
		}
	}
}

func TestPollRequestError(t *testing.T) {
	const opName = "foo"

	// All calls error.
	s := &getterService{}
	op := &Operation{
		c:     s,
		proto: &pb.Operation{Name: opName},
	}
	if err := op.Poll(context.Background(), nil); err == nil {
		t.Fatalf("Poll should error")
	}
	if n := op.Name(); n != opName {
		t.Errorf("operation name, got %q, want %q", n, opName)
	}
	if op.Done() {
		t.Errorf("operation should not have completed; we failed to fetch state")
	}
}

func TestPollErrorResult(t *testing.T) {
	const (
		errCode = codes.NotFound
		errMsg  = "my error"
	)
	details := &errdetails.ErrorInfo{Reason: "things happen"}
	a, err := anypb.New(details)
	if err != nil {
		t.Fatalf("anypb.New() = %v", err)
	}
	op := &Operation{
		proto: &pb.Operation{
			Name: "foo",
			Done: true,
			Result: &pb.Operation_Error{
				Error: &rpcstatus.Status{
					Code:    int32(errCode),
					Message: errMsg,
					Details: []*anypb.Any{a},
				},
			},
		},
	}
	err = op.Poll(context.Background(), nil)
	if got := status.Code(err); got != errCode {
		t.Errorf("error code, want %s, got %s", errCode, got)
	}
	if got := grpc.ErrorDesc(err); got != errMsg {
		t.Errorf("error code, want %s, got %s", errMsg, got)
	}
	if !op.Done() {
		t.Errorf("operation should have completed")
	}
	var ae *apierror.APIError
	errors.As(err, &ae)
	if got := ae.Details().ErrorInfo.Reason; got != details.Reason {
		t.Errorf("got %q, want %q", got, details.Reason)
	}
}

type errService struct {
	operationsClient
	errCancel, errDelete error
}

func (s *errService) CancelOperation(context.Context, *pb.CancelOperationRequest, ...gax.CallOption) error {
	return s.errCancel
}

func (s *errService) DeleteOperation(context.Context, *pb.DeleteOperationRequest, ...gax.CallOption) error {
	return s.errDelete
}

func TestCancelReturnsError(t *testing.T) {
	s := &errService{
		errCancel: errors.New("cancel error"),
	}
	op := &Operation{
		c:     s,
		proto: &pb.Operation{Name: "foo"},
	}
	if got, want := op.Cancel(context.Background()), s.errCancel; got != want {
		t.Errorf("cancel, got error %s, want %s", got, want)
	}
}

func TestDeleteReturnsError(t *testing.T) {
	s := &errService{
		errDelete: errors.New("delete error"),
	}
	op := &Operation{
		c:     s,
		proto: &pb.Operation{Name: "foo"},
	}
	if got, want := op.Delete(context.Background()), s.errDelete; got != want {
		t.Errorf("cancel, got error %s, want %s", got, want)
	}
}
