package ci_test

import (
	"testing"

	"github.com/google/osv-scanner/v2/internal/ci"
	"github.com/google/osv-scanner/v2/internal/testutility"
	"github.com/google/osv-scanner/v2/pkg/models"
)

func TestDiffVulnerabilityResults(t *testing.T) {
	t.Parallel()
	type args struct {
		oldRes models.VulnerabilityResults
		newRes models.VulnerabilityResults
	}
	tests := []struct {
		name string
		args args
	}{
		{
			// diff should be empty since the old and new results are the same
			name: "same_everything",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
			},
		},
		{
			// diff should have the moved package only
			name: "same_packages_but_with_one_moved",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a-1.json"),
			},
		},
		{
			// diff should have just the new vuln
			name: "same_packages_with_new_vuln",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-b.json"),
			},
		},
		{
			// diff should be empty
			name: "new_has_one_less_vuln",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-b.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
			},
		},
		{
			// diff should have all the new vulns
			name: "new_vuln_and_packages",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-c.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-b.json"),
			},
		},
		{
			// diff should have no vulns
			name: "old_vuln_and_packages_gone",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-b.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-c.json"),
			},
		},
		{
			// diff should be empty since new package does not have any vulns
			name: "old_package_replaced_with_new_package",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-d.json"),
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			got := ci.DiffVulnerabilityResults(tt.args.oldRes, tt.args.newRes)
			testutility.NewSnapshot().MatchJSON(t, got)
		})
	}
}

func TestDiffVulnerabilityByUniqueVulnCountResults(t *testing.T) {
	t.Parallel()
	type args struct {
		oldRes models.VulnerabilityResults
		newRes models.VulnerabilityResults
	}
	tests := []struct {
		name string
		args args
	}{
		{
			// diff should be empty
			name: "same_packages_with_different_source_path",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a-1.json"),
			},
		},
		{
			// diff should be empty
			name: "same_everything",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
			},
		},
		{
			// diff should have just the new vuln
			name: "same_package_with_new_vuln",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-b.json"),
			},
		},
		{
			// diff should be empty
			name: "new_has_one_less_vuln",
			args: args{
				oldRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-b.json"),
				newRes: testutility.LoadJSONFixture[models.VulnerabilityResults](t, "testdata/vulns/test-vuln-results-a.json"),
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			got := ci.DiffVulnerabilityResultsByOccurrences(tt.args.oldRes, tt.args.newRes)
			testutility.NewSnapshot().MatchJSON(t, got)
		})
	}
}
