package catalogapp

import (
	"context"
	"database/sql"

	"github.com/pingcap-inc/nexuscrm-contract/pkg/appauthority"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/layoutbundleslotv1"
)

// insertReleaseGraphTx is the sole writer for the immutable release-owned
// dependency, namespace, capability, component, and LayoutBundle-slot graph.
// The caller owns the admission-specific parent row and provenance receipt.
func insertReleaseGraphTx(
	ctx context.Context,
	tx *sql.Tx,
	verified appauthority.VerifiedPackage,
	slotDeclarations []layoutbundleslotv1.Declaration,
) error {
	manifest := verified.Manifest
	for _, dependency := range manifest.Dependencies {
		required, err := marshalJSON(dependency.RequiredCapabilities)
		if err != nil {
			return err
		}
		if _, err := tx.ExecContext(ctx, `INSERT INTO _System_CatalogAppReleaseDependency
(AppId, AppReleaseDigest, Alias, DependencyAppId, MinimumVersionInclusive, MaximumVersionExclusive, RequiredCapabilities)
VALUES (?, ?, ?, ?, ?, ?, CAST(? AS JSON))`, manifest.AppID, verified.AppReleaseDigest, dependency.Alias, dependency.AppID, dependency.MinimumVersionInclusive, dependency.MaximumVersionExclusive, required); err != nil {
			return err
		}
	}
	for _, namespace := range manifest.OwnedNamespaces {
		if _, err := tx.ExecContext(ctx, `INSERT INTO _System_CatalogAppReleaseNamespace
(AppId, AppReleaseDigest, NamespaceId) VALUES (?, ?, ?)`, manifest.AppID, verified.AppReleaseDigest, namespace); err != nil {
			return err
		}
	}
	for _, capability := range manifest.ProvidedCapabilities {
		required, err := marshalJSON(capability.RequiredRuntimeCapabilities)
		if err != nil {
			return err
		}
		if _, err := tx.ExecContext(ctx, `INSERT INTO _System_CatalogAppReleaseCapability
(AppId, AppReleaseDigest, CapabilityId, Kind, HandlerRef, RequiredRuntimeCapabilities)
VALUES (?, ?, ?, ?, ?, CAST(? AS JSON))`, manifest.AppID, verified.AppReleaseDigest, capability.CapabilityID, capability.Kind, nullableString(capability.HandlerRef), required); err != nil {
			return err
		}
	}
	for i, component := range verified.Bundle.Components {
		if _, err := tx.ExecContext(ctx, `INSERT INTO _System_CatalogAppReleaseComponent
(AppId, AppReleaseDigest, ComponentId, NamespaceId, ComponentKind, BusinessKey, DefinitionVersion, ContentDigest, CanonicalBehavior)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, manifest.AppID, verified.AppReleaseDigest, component.ComponentID, component.NamespaceID, component.ComponentKind, component.BusinessKey, component.DefinitionVersion, component.ContentDigest, verified.ComponentBlobs[i].CanonicalBehavior); err != nil {
			return err
		}
	}
	return registerReleaseLayoutBundleSlotsTx(
		ctx,
		tx,
		manifest.AppID,
		verified.AppReleaseDigest,
		slotDeclarations,
	)
}
