package runtimeapi

import (
	"context"
	"strings"
	"testing"

	"github.com/nexuscrm/metadata/catalogsnapshot"
	approvalsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/approvalv1"
	mutationsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordmutationv1"
)

func newApprovalServingFixture(
	t *testing.T,
	snapshotArtifact catalogsnapshot.Artifact,
	views map[string]catalogsnapshot.Artifact,
) *ServingAdmission {
	t.Helper()
	appReleaseDigest := catalogsnapshot.ComputeDigest([]byte("approval-app-release"))
	serviceReleaseDigest := catalogsnapshot.ComputeDigest([]byte("approval-service-release"))
	store, err := catalogsnapshot.NewDirectoryStore(t.TempDir())
	if err != nil {
		t.Fatal(err)
	}
	if err := store.Put(t.Context(), snapshotArtifact); err != nil {
		t.Fatal(err)
	}
	installation := ServingInstallation{
		OrgID: testOrgID, AppInstallationID: testInstallationID,
		ActiveReleaseDigest: string(appReleaseDigest), CatalogRevision: 71,
	}
	bindings := make(map[string]ServingHandlerBinding, len(views))
	selections := make([]ServingSelection, 0, len(views))
	for _, capability := range []string{
		approvalsemantic.ExecuteCapabilityName,
		approvalsemantic.ReadCapabilityName,
		mutationsemantic.CapabilityName,
	} {
		viewArtifact, ok := views[capability]
		if !ok {
			continue
		}
		if err := store.Put(t.Context(), viewArtifact); err != nil {
			t.Fatal(err)
		}
		appCapabilityID := "io.nexuscrm.sfcrm." + strings.ReplaceAll(capability, "_", "-")
		receipt := servingReceipt(
			t, snapshotArtifact, viewArtifact, 71,
			appReleaseDigest, serviceReleaseDigest, 3,
			appCapabilityID, capability,
		)
		if err := store.Put(t.Context(), receipt); err != nil {
			t.Fatal(err)
		}
		bindings[appCapabilityID] = ServingHandlerBinding{
			OrgID: testOrgID, AppInstallationID: testInstallationID,
			AppReleaseDigest: string(appReleaseDigest), CapabilityID: appCapabilityID,
			WorkloadID: testWorkloadID, ServiceReleaseDigest: string(serviceReleaseDigest),
			OwnershipEpoch: 3, CompatibilityReceiptDigest: string(receipt.Digest()),
		}
		selections = append(selections, ServingSelection{
			OrgID: testOrgID, AppInstallationID: testInstallationID,
			ExpectedWorkloadID: testWorkloadID,
			AppCapabilityID:    appCapabilityID, RuntimeCapabilityID: capability,
			ExpectedServiceReleaseDigest:       serviceReleaseDigest,
			ExpectedOwnershipEpoch:             3,
			ExpectedCompatibilityReceiptDigest: receipt.Digest(),
			LocalCompatibility: catalogsnapshot.Compatibility{
				SchemaGeneration: 8, EngineGeneration: 9,
			},
			SecurityEpoch: 1,
		})
	}
	state, err := NewServingState(ServingStateConfig{
		Store: store,
		Catalog: func(
			_ context.Context,
			installationID string,
			capabilityID string,
		) (ServingInstallation, ServingHandlerBinding, bool, error) {
			binding, ok := bindings[capabilityID]
			if installationID != testInstallationID || !ok {
				return ServingInstallation{}, ServingHandlerBinding{}, false, nil
			}
			return installation, binding, true, nil
		},
	})
	if err != nil {
		t.Fatal(err)
	}
	if err := state.ReconcileAll(t.Context(), selections); err != nil {
		t.Fatal(err)
	}
	admission, err := NewServingAdmission(state)
	if err != nil {
		t.Fatal(err)
	}
	return admission
}
