package metadata

import (
	"testing"
	"text/template"
	"time"

	"github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate/mocks"
	"k8s.io/utils/ptr"
)

func TestKeeperQueries(t *testing.T) {
	mocks.CheckQuerySnapshots(t, mocks.TemplateTestSetup{
		RootDir: "testdata",
		Templates: map[*template.Template][]mocks.TemplateTestCase{
			sqlKeeperSetAsActive: {
				{
					Name: "keeper set as active",
					Data: &setKeeperAsActive{
						SQLTemplate: mocks.NewTestingSQLTemplate(), Name: "name",
						Namespace: "ns",
					},
				},
			},
			sqlKeeperCreate: {
				{
					Name: "create",
					Data: &createKeeper{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Row: &keeperDB{
							GUID:        "abc",
							Name:        "name",
							Namespace:   "ns",
							Annotations: `{"x":"XXXX"}`,
							Labels:      `{"a":"AAA", "b", "BBBB"}`,
							Created:     1234,
							CreatedBy:   "user:ryan",
							Updated:     5678,
							UpdatedBy:   "user:cameron",
							Description: "description",
							Type:        "sql",
							Payload:     "",
						},
					},
				},
			},
			sqlKeeperDelete: {
				{
					Name: "delete",
					Data: &deleteKeeper{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Name:        "name",
						Namespace:   "ns",
					},
				},
			},
			sqlKeeperList: {
				{
					Name: "list",
					Data: &listKeeper{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Namespace:   "ns",
					},
				},
			},
			sqlKeeperReadActive: {
				{
					Name: "read active",
					Data: &readActiveKeeper{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Namespace:   "ns",
					},
				},
			},
			sqlKeeperRead: {
				{
					Name: "read",
					Data: &readKeeper{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Name:        "name",
						Namespace:   "ns",
					},
				},
				{
					Name: "read-for-update",
					Data: &readKeeper{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Name:        "name",
						Namespace:   "ns",
						IsForUpdate: true,
					},
				},
			},
			sqlKeeperUpdate: {
				{
					Name: "update",
					Data: &updateKeeper{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Row: &keeperDB{
							GUID:        "abc",
							Name:        "name",
							Namespace:   "ns",
							Annotations: `{"x":"XXXX"}`,
							Labels:      `{"a":"AAA", "b", "BBBB"}`,
							Created:     1234,
							CreatedBy:   "user:ryan",
							Updated:     5678,
							UpdatedBy:   "user:cameron",
							Description: "description",
							Type:        "sql",
							Payload:     "",
						},
					},
				},
			},
			sqlKeeperListByName: {
				{
					Name: "list",
					Data: listByNameKeeper{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Namespace:   "ns",
						KeeperNames: []string{"a", "b"},
					},
				},
			},
			sqlSecureValueListByName: {
				{
					Name: "list",
					Data: listByNameSecureValue{
						SQLTemplate:      mocks.NewTestingSQLTemplate(),
						Namespace:        "ns",
						UsedSecureValues: []string{"a", "b"},
					},
				},
			},
		},
	})
}

func TestSecureValueQueries(t *testing.T) {
	mocks.CheckQuerySnapshots(t, mocks.TemplateTestSetup{
		RootDir: "testdata",
		Templates: map[*template.Template][]mocks.TemplateTestCase{
			sqlGetLatestSecureValueVersionAndCreatedAt: {
				{
					Name: "get latest secure value version",
					Data: &getLatestSecureValueVersionAndCreatedAt{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Name:        "name",
						Namespace:   "ns",
					},
				},
			},
			sqlSecureValueSetVersionToActive: {
				{
					Name: "set secure value version to active",
					Data: &secureValueSetVersionToActive{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Name:        "name",
						Namespace:   "ns",
						Version:     1,
					},
				},
			},
			sqlSecureValueRead: {
				{
					Name: "read",
					Data: &readSecureValue{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Name:        "name",
						Namespace:   "ns",
					},
				},
				{
					Name: "read-for-update",
					Data: &readSecureValue{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Name:        "name",
						Namespace:   "ns",
						IsForUpdate: true,
					},
				},
			},
			sqlSecureValueList: {
				{
					Name: "list",
					Data: &listSecureValue{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Namespace:   "ns",
					},
				},
			},
			sqlSecureValueCreate: {
				{
					Name: "create-null",
					Data: &createSecureValue{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Row: &secureValueDB{
							GUID:                     "abc",
							Name:                     "name",
							Namespace:                "ns",
							Annotations:              `{"x":"XXXX"}`,
							Labels:                   `{"a":"AAA", "b", "BBBB"}`,
							Created:                  1234,
							CreatedBy:                "user:ryan",
							Updated:                  5678,
							UpdatedBy:                "user:cameron",
							Version:                  1,
							Description:              "description",
							Keeper:                   toNullString(nil),
							Decrypters:               toNullString(nil),
							Ref:                      toNullString(nil),
							ExternalID:               "extId",
							OwnerReferenceAPIGroup:   toNullString(nil),
							OwnerReferenceAPIVersion: toNullString(nil),
							OwnerReferenceKind:       toNullString(nil),
							OwnerReferenceName:       toNullString(nil),
						},
					},
				},
				{
					Name: "create-not-null",
					Data: &createSecureValue{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Row: &secureValueDB{
							GUID:                     "abc",
							Name:                     "name",
							Namespace:                "ns",
							Annotations:              `{"x":"XXXX"}`,
							Labels:                   `{"a":"AAA", "b", "BBBB"}`,
							Created:                  1234,
							CreatedBy:                "user:ryan",
							Updated:                  5678,
							UpdatedBy:                "user:cameron",
							Version:                  1,
							Description:              "description",
							Keeper:                   toNullString(ptr.To("keeper_test")),
							Decrypters:               toNullString(ptr.To("decrypters_test")),
							Ref:                      toNullString(ptr.To("ref_test")),
							ExternalID:               "extId",
							OwnerReferenceAPIGroup:   toNullString(ptr.To("prometheus.datasource.grafana.app")),
							OwnerReferenceAPIVersion: toNullString(ptr.To("v0alpha1")),
							OwnerReferenceKind:       toNullString(ptr.To("DataSource")),
							OwnerReferenceName:       toNullString(ptr.To("prom-config")),
						},
					},
				},
			},
			sqlSecureValueUpdateExternalId: {
				{
					Name: "updateExternalId",
					Data: &updateExternalIdSecureValue{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Name:        "name",
						Namespace:   "ns",
						ExternalID:  "extId",
					},
				},
			},
			sqlSecureValueDelete: {
				{
					Name: "deleteSecureValue",
					Data: &deleteSecureValue{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						Namespace:   "ns",
						Name:        "name",
						Version:     1,
					},
				},
			},
			sqlSecureValueLeaseInactive: {
				{
					Name: "lease inactive",
					Data: &leaseInactiveSecureValues{
						SQLTemplate:  mocks.NewTestingSQLTemplate(),
						Now:          10,
						LeaseToken:   "token",
						LeaseTTL:     int64((30 * time.Second).Seconds()),
						MaxBatchSize: 10,
						MinAge:       int64((300 * time.Second).Seconds()),
					},
				},
			},
			sqlSecureValueListByLeaseToken: {
				{
					Name: "list by lease token",
					Data: &listSecureValuesByLeaseToken{
						SQLTemplate: mocks.NewTestingSQLTemplate(),
						LeaseToken:  "token",
					},
				},
			},
		},
	})
}
