package main

import (
	"errors"
	"testing"

	"go.uber.org/mock/gomock"
	"src.opensuse.org/autogits/common"
	"src.opensuse.org/autogits/common/gitea-generated/models"
	mock_common "src.opensuse.org/autogits/common/mock"
)

func TestReviews(t *testing.T) {
	tests := []struct {
		name       string
		reviews    []*models.PullReview
		reviewers  []string
		fetchErr   error
		isReviewed bool
	}{
		{
			name:       "Reviews of unreviews PR",
			isReviewed: false,
		},
		{
			name:       "Single reviewer done",
			reviews:    []*models.PullReview{&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}}},
			reviewers:  []string{"user1"},
			isReviewed: true,
		},
		{
			name:       "Two reviewer, one not approved",
			reviews:    []*models.PullReview{&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}}},
			reviewers:  []string{"user1", "user2"},
			isReviewed: false,
		},
		{
			name: "Two reviewer, one stale approved",
			reviews: []*models.PullReview{
				&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}},
				&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}, Stale: true},
			},
			reviewers:  []string{"user1", "user2"},
			isReviewed: false,
		},
		{
			name: "Two reviewer approved",
			reviews: []*models.PullReview{
				&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}},
				&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}},
			},
			reviewers:  []string{"user1", "user2"},
			isReviewed: true,
		},
		{
			name: "Two reviewer approved, but fetch error",
			reviews: []*models.PullReview{
				&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}},
				&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}},
			},
			reviewers:  []string{"user1", "user2"},
			fetchErr:   errors.New("System error fetching reviews."),
			isReviewed: true,
		},
		{
			name: "Extra reviewers are ignored",
			reviews: []*models.PullReview{
				&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}},
				&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user4"}},
				&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}},
			},
			reviewers:  []string{"user1", "user2"},
			isReviewed: true,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			ctl := gomock.NewController(t)
			rf := mock_common.NewMockGiteaReviewFetcher(ctl)

			rf.EXPECT().GetPullRequestReviews("test", "pr", int64(1)).Return(test.reviews, test.fetchErr)

			reviews, err := FetchGiteaReviews(rf, test.reviewers, "test", "pr", 1)

			if test.fetchErr != nil {
				if err != test.fetchErr {
					t.Fatal("FetchReviews() failed with unexpected error:", err)
				}
				return
			}

			if r := reviews.IsReviewed(); r != test.isReviewed {
				t.Fatal("Unexpected IsReviewed():", r, "vs. expected", test.isReviewed)
			}
		})
	}
}
