package model

import (
	"testing"

	"github.com/stretchr/testify/assert"

	"github.com/anchore/grype/grype/db/internal/sqlite"
	v5 "github.com/anchore/grype/grype/db/v5"
)

func TestVulnerabilityMatchExclusionModel_Inflate(t *testing.T) {
	tests := []struct {
		name   string
		record *VulnerabilityMatchExclusionModel
		result *v5.VulnerabilityMatchExclusion
	}{
		{
			name: "Nil constraint",
			record: &VulnerabilityMatchExclusionModel{
				PK:            0,
				ID:            "CVE-12345",
				Constraints:   sqlite.ToNullString(nil),
				Justification: "Who really knows?",
			},
			result: &v5.VulnerabilityMatchExclusion{
				ID:            "CVE-12345",
				Constraints:   nil,
				Justification: "Who really knows?",
			},
		},
		{
			name: "Empty constraint array",
			record: &VulnerabilityMatchExclusionModel{
				PK:            0,
				ID:            "CVE-919",
				Constraints:   sqlite.NewNullString(`[]`, true),
				Justification: "Always ignore",
			},
			result: &v5.VulnerabilityMatchExclusion{
				ID:            "CVE-919",
				Constraints:   nil,
				Justification: "Always ignore",
			},
		},
		{
			name: "Single constraint",
			record: &VulnerabilityMatchExclusionModel{
				PK:            0,
				ID:            "CVE-919",
				Constraints:   sqlite.NewNullString(`[{"vulnerability":{"namespace":"nvd:cpe"},"package":{"language":"python"}}]`, true),
				Justification: "Python packages are not vulnerable",
			},
			result: &v5.VulnerabilityMatchExclusion{
				ID: "CVE-919",
				Constraints: []v5.VulnerabilityMatchExclusionConstraint{
					{
						Vulnerability: v5.VulnerabilityExclusionConstraint{
							Namespace: "nvd:cpe",
						},
						Package: v5.PackageExclusionConstraint{
							Language: "python",
						},
					},
				},
				Justification: "Python packages are not vulnerable",
			},
		},
		{
			name: "Single unusable constraint with unknown vulnerability constraint field",
			record: &VulnerabilityMatchExclusionModel{
				PK:            0,
				ID:            "CVE-919",
				Constraints:   sqlite.NewNullString(`[{"vulnerability":{"namespace":"nvd:cpe","something_new":"1234"}}]`, true),
				Justification: "Python packages are not vulnerable",
			},
			result: nil,
		},
		{
			name: "Single unusable constraint with unknown package constraint fields",
			record: &VulnerabilityMatchExclusionModel{
				PK:            0,
				ID:            "CVE-919",
				Constraints:   sqlite.NewNullString(`[{"package":{"name":"jim","another_field":"1234","x_y_z":"abc"}}]`, true),
				Justification: "Python packages are not vulnerable",
			},
			result: nil,
		},
		{
			name: "Single unusable constraint with unknown root-level constraint fields",
			record: &VulnerabilityMatchExclusionModel{
				PK:            0,
				ID:            "CVE-919",
				Constraints:   sqlite.NewNullString(`[{"x_y_z":{"name":"jim","another_field":"1234","x_y_z":"abc"},"package":{"name":"jim","another_field":"1234","x_y_z":"abc"}}]`, true),
				Justification: "Python packages are not vulnerable",
			},
			result: nil,
		},
		{
			name: "Multiple usable constraints",
			record: &VulnerabilityMatchExclusionModel{
				PK:            0,
				ID:            "CVE-2025-152345",
				Constraints:   sqlite.NewNullString(`[{"vulnerability":{"namespace":"abc.xyz:language:ruby","fix_state":"wont-fix"},"package":{"language":"ruby","type":"not-gem"}},{"package":{"language":"python","version":"1000.0.1"}},{"vulnerability":{"namespace":"nvd:cpe"}},{"vulnerability":{"namespace":"nvd:cpe"},"package":{"name":"x"}},{"package":{"location":"/bin/x"}}]`, true),
				Justification: "Python packages are not vulnerable",
			},
			result: &v5.VulnerabilityMatchExclusion{
				ID: "CVE-2025-152345",
				Constraints: []v5.VulnerabilityMatchExclusionConstraint{
					{
						Vulnerability: v5.VulnerabilityExclusionConstraint{
							Namespace: "abc.xyz:language:ruby",
							FixState:  "wont-fix",
						},
						Package: v5.PackageExclusionConstraint{
							Language: "ruby",
							Type:     "not-gem",
						},
					},
					{
						Package: v5.PackageExclusionConstraint{
							Language: "python",
							Version:  "1000.0.1",
						},
					},
					{
						Vulnerability: v5.VulnerabilityExclusionConstraint{
							Namespace: "nvd:cpe",
						},
					},
					{
						Vulnerability: v5.VulnerabilityExclusionConstraint{
							Namespace: "nvd:cpe",
						},
						Package: v5.PackageExclusionConstraint{
							Name: "x",
						},
					},
					{
						Package: v5.PackageExclusionConstraint{
							Location: "/bin/x",
						},
					},
				},
				Justification: "Python packages are not vulnerable",
			},
		},
		{
			name: "Multiple constraints with some unusable",
			record: &VulnerabilityMatchExclusionModel{
				PK:            0,
				ID:            "CVE-2025-152345",
				Constraints:   sqlite.NewNullString(`[{"a_b_c": "x","vulnerability":{"namespace":"abc.xyz:language:ruby","fix_state":"wont-fix"},"package":{"language":"ruby","type":"not-gem"}},{"package":{"language":"python","version":"1000.0.1"}},{"vulnerability":{"namespace":"nvd:cpe"}},{"vulnerability":{"namespace":"nvd:cpe"},"package":{"name":"x"}},{"package":{"location":"/bin/x","nnnn":"no"}}]`, true),
				Justification: "Python packages are not vulnerable",
			},
			result: &v5.VulnerabilityMatchExclusion{
				ID: "CVE-2025-152345",
				Constraints: []v5.VulnerabilityMatchExclusionConstraint{
					{
						Package: v5.PackageExclusionConstraint{
							Language: "python",
							Version:  "1000.0.1",
						},
					},
					{
						Vulnerability: v5.VulnerabilityExclusionConstraint{
							Namespace: "nvd:cpe",
						},
					},
					{
						Vulnerability: v5.VulnerabilityExclusionConstraint{
							Namespace: "nvd:cpe",
						},
						Package: v5.PackageExclusionConstraint{
							Name: "x",
						},
					},
				},
				Justification: "Python packages are not vulnerable",
			},
		},
		{
			name: "Multiple constraints all unusable",
			record: &VulnerabilityMatchExclusionModel{
				PK:            0,
				ID:            "CVE-2025-152345",
				Constraints:   sqlite.NewNullString(`[{"a_b_c": "x","vulnerability":{"namespace":"abc.xyz:language:ruby","fix_state":"wont-fix"},"package":{"language":"ruby","type":"not-gem"}},{"a_b_c": "x","package":{"language":"python","version":"1000.0.1"}},{"a_b_c": "x","vulnerability":{"namespace":"nvd:cpe"}},{"a_b_c": "x","vulnerability":{"namespace":"nvd:cpe"},"package":{"name":"x"}},{"package":{"location":"/bin/x","nnnn":"no"}}]`, true),
				Justification: "Python packages are not vulnerable",
			},
			result: nil,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			result, err := test.record.Inflate()
			assert.NoError(t, err)
			assert.Equal(t, test.result, result)
		})
	}
}
