package cases

import (
	"errors"
	"fmt"
	"io"
	"testing"

	"github.com/avast/retry-go/v4"
)

func TestCheckStillStatus(t *testing.T) {
	stateChanged := errors.New("state changed")
	tests := map[string]struct {
		results   []error
		wantCalls int
		wantErr   error
	}{
		"expected state does not retry": {
			results:   []error{nil},
			wantCalls: 1,
		},
		"unexpected EOF retries once": {
			results:   []error{fmt.Errorf("get changefeed: %w", io.ErrUnexpectedEOF), nil},
			wantCalls: 2,
		},
		"repeated unexpected EOF remains an error": {
			results:   []error{io.ErrUnexpectedEOF, io.ErrUnexpectedEOF},
			wantCalls: 2,
			wantErr:   io.ErrUnexpectedEOF,
		},
		"state mismatch does not retry": {
			results:   []error{stateChanged},
			wantCalls: 1,
			wantErr:   stateChanged,
		},
	}

	for name, tc := range tests {
		t.Run(name, func(t *testing.T) {
			calls := 0
			gotErr := checkStillStatus(func() error {
				result := tc.results[calls]
				calls++
				return result
			})

			if calls != tc.wantCalls {
				t.Fatalf("calls = %d, want %d", calls, tc.wantCalls)
			}
			if !errors.Is(gotErr, tc.wantErr) {
				t.Fatalf("error = %v, want %v", gotErr, tc.wantErr)
			}
		})
	}
}

type codedHTTPError int

func (e codedHTTPError) Error() string { return "HTTP error" }
func (e codedHTTPError) Code() int     { return int(e) }

func TestStopRetryOnHTTP401SupportsGeneratedResponseErrors(t *testing.T) {
	for _, tc := range []struct {
		name      string
		code      int
		wantCalls int
	}{
		{name: "unauthorized is terminal", code: 401, wantCalls: 1},
		{name: "server error remains retryable", code: 500, wantCalls: 3},
	} {
		t.Run(tc.name, func(t *testing.T) {
			calls := 0
			_ = retry.Do(func() error {
				calls++
				return stopRetryOnHTTP401(codedHTTPError(tc.code))
			}, retry.Attempts(3))
			if calls != tc.wantCalls {
				t.Fatalf("calls = %d, want %d", calls, tc.wantCalls)
			}
		})
	}
}
