package github_test

import (
	"bytes"
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
	ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
	"github.com/aquasecurity/trivy/pkg/report/github"
	"github.com/aquasecurity/trivy/pkg/types"
)

func TestWriter_Write(t *testing.T) {
	tests := []struct {
		name   string
		report types.Report
		want   map[string]github.Manifest
	}{
		{
			name: "os packages",
			report: types.Report{
				SchemaVersion: 2,
				ArtifactName:  "alpine:3.14",
				Metadata: types.Metadata{
					OS: &ftypes.OS{
						Family: "alpine",
						Name:   "3.14",
						Eosl:   true,
					},
				},
				Results: types.Results{
					{
						Target: "yarn.lock",
						Class:  "lang-pkgs",
						Type:   "yarn",
						Packages: []ftypes.Package{
							{
								Name:         "@xtuc/ieee754",
								Version:      "1.2.0",
								Relationship: ftypes.RelationshipDirect,
							},
							{
								Name:         "@xtuc/long",
								Version:      "4.2.2",
								Relationship: ftypes.RelationshipDirect,
							},
							{
								Name:         "@xtuc/binaryen",
								Version:      "1.37.33",
								Relationship: ftypes.RelationshipIndirect,
							},
						},
						Vulnerabilities: []types.DetectedVulnerability{
							{
								VulnerabilityID:  "CVE-2020-0001",
								PkgName:          "foo",
								InstalledVersion: "1.2.3",
								FixedVersion:     "3.4.5",
								PrimaryURL:       "https://avd.aquasec.com/nvd/cve-2020-0001",
								Vulnerability: dbTypes.Vulnerability{
									Title:       "foobar",
									Description: "baz",
									Severity:    "HIGH",
								},
							},
						},
					},
					{
						Target: "alpine:3.14 (alpine 3.14.10)",
						Class:  "os-pkgs",
						Type:   "alpine",
						Packages: []ftypes.Package{
							{
								ID:         "apk-tools@2.12.7-r0",
								Name:       "apk-tools",
								Version:    "2.12.7-r0",
								Arch:       "x86_64",
								SrcName:    "apk-tools",
								SrcVersion: "2.12.7-r0",
							},
						},
					},
				},
			},
			want: map[string]github.Manifest{
				"alpine:3.14 (alpine 3.14.10)": {
					Name: "alpine",
					Resolved: map[string]github.Package{
						"apk-tools": {
							PackageUrl:   "pkg:apk/alpine/apk-tools@2.12.7-r0?arch=x86_64&distro=3.14",
							Relationship: "direct",
							Scope:        "runtime",
						},
					},
				},
				"yarn.lock": {
					Name: "yarn",
					File: &github.File{
						SrcLocation: "yarn.lock",
					},
					Resolved: map[string]github.Package{
						"@xtuc/ieee754": {
							PackageUrl:   "pkg:npm/%40xtuc/ieee754@1.2.0",
							Relationship: "direct",
							Scope:        "runtime",
						},
						"@xtuc/long": {
							PackageUrl:   "pkg:npm/%40xtuc/long@4.2.2",
							Relationship: "direct",
							Scope:        "runtime",
						},
						"@xtuc/binaryen": {
							PackageUrl:   "pkg:npm/%40xtuc/binaryen@1.37.33",
							Relationship: "indirect",
							Scope:        "runtime",
						},
					},
				},
			},
		},
		{
			name: "maven",
			report: types.Report{
				SchemaVersion: 2,
				ArtifactName:  "my-java-app",
				Results: types.Results{
					{
						Target: "pom.xml",
						Class:  "lang-pkgs",
						Type:   "pom",
						Packages: []ftypes.Package{
							{
								Name:    "com.google.code.gson:gson",
								Version: "2.2.2",
							},
							{
								Name:    "net.sf.opencsv:opencsv",
								Version: "2.3",
							},
						},
					},
				},
			},
			want: map[string]github.Manifest{
				"pom.xml": {
					Name: "pom",
					File: &github.File{
						SrcLocation: "pom.xml",
					},
					Resolved: map[string]github.Package{
						"com.google.code.gson:gson": {
							PackageUrl:   "pkg:maven/com.google.code.gson/gson@2.2.2",
							Relationship: "direct",
							Scope:        "runtime",
						},
						"net.sf.opencsv:opencsv": {
							PackageUrl:   "pkg:maven/net.sf.opencsv/opencsv@2.3",
							Relationship: "direct",
							Scope:        "runtime",
						},
					},
				},
			},
		},
		{
			name: "pypi from image",
			report: types.Report{
				SchemaVersion: 2,
				ArtifactName:  "fake_repo.azurecr.io/image_name",
				ArtifactType:  "container_image",
				Metadata: types.Metadata{
					RepoDigests: []string{"fake_repo.azurecr.io/image_name@sha256:a7c92cdcb3d010f6edeb37ddcdbacab14981aa31e7f1140e0097dc1b8e834c49"},
					RepoTags:    []string{"fake_repo.azurecr.io/image_name:latest"},
				},
				Results: types.Results{
					{
						Target: "Python",
						Class:  "lang-pkgs",
						Type:   "python-pkg",
						Packages: []ftypes.Package{
							{
								Name:    "jwcrypto",
								Version: "0.7",
								Licenses: []string{
									"LGPLv3+",
								},
								Layer: ftypes.Layer{
									Digest: "sha256:ddc612ba4e74ea5633a93e19e7c32f61f5f230073b21a070302a61ef5eec5c50",
									DiffID: "sha256:12935ef6ce21a266aef8df75d601cebf7e935edd01e9f19fab16ccb78fbb9a5e",
								},
								FilePath: "opt/pyenv/versions/3.11.2/lib/python3.11/site-packages/jwcrypto-0.7.dist-info/METADATA",
							},
							{
								Name:    "matplotlib",
								Version: "3.5.3",
								Licenses: []string{
									"PSF",
								},
								Layer: ftypes.Layer{
									Digest: "sha256:ddc612ba4e74ea5633a93e19e7c32f61f5f230073b21a070302a61ef5eec5c50",
									DiffID: "sha256:12935ef6ce21a266aef8df75d601cebf7e935edd01e9f19fab16ccb78fbb9a5e",
								},
								FilePath: "opt/pyenv/versions/3.11.2/lib/python3.11/site-packages/matplotlib-3.5.3.dist-info/METADATA",
							},
						},
					},
				},
			},
			want: map[string]github.Manifest{
				"Python": {
					Name: "python-pkg",
					File: &github.File{
						SrcLocation: "fake_repo.azurecr.io/image_name:latest@sha256:a7c92cdcb3d010f6edeb37ddcdbacab14981aa31e7f1140e0097dc1b8e834c49",
					},
					Resolved: map[string]github.Package{
						"jwcrypto": {
							PackageUrl:   "pkg:pypi/jwcrypto@0.7",
							Relationship: "direct",
							Scope:        "runtime",
							Metadata:     github.Metadata{"source_location": "opt/pyenv/versions/3.11.2/lib/python3.11/site-packages/jwcrypto-0.7.dist-info/METADATA"},
						},
						"matplotlib": {
							PackageUrl:   "pkg:pypi/matplotlib@3.5.3",
							Relationship: "direct",
							Scope:        "runtime",
							Metadata:     github.Metadata{"source_location": "opt/pyenv/versions/3.11.2/lib/python3.11/site-packages/matplotlib-3.5.3.dist-info/METADATA"},
						},
					},
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			written := bytes.NewBuffer(nil)
			w := github.Writer{
				Output: written,
			}

			inputResults := tt.report

			err := w.Write(t.Context(), inputResults)
			require.NoError(t, err)

			var got github.DependencySnapshot
			err = json.Unmarshal(written.Bytes(), &got)
			require.NoError(t, err, "invalid github written")
			assert.Equal(t, tt.want, got.Manifests, tt.name)
		})
	}
}
