package persistence

import (
	"context"
	"database/sql"
	"fmt"
	"strings"

	domainschema "github.com/nexuscrm/kernel/pkg/schema"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
)

func (r *SchemaRepository) preservePackOwnedAccessPolicySidecarsForObjectMetadata(ctx context.Context, exec Executor, obj *models.ObjectMetadata) error {
	if exec == nil || obj == nil || strings.TrimSpace(obj.APIName) == "" {
		return nil
	}

	var liveRaw, recordMutationPackName, recordMutationPackValue, lifecyclePackName, lifecyclePackValue sql.NullString
	err := exec.QueryRowContext(ctx,
		fmt.Sprintf(
			"SELECT `%s`, `%s`, `%s`, `%s`, `%s` FROM `%s` WHERE LOWER(`%s`) = ? AND COALESCE(`%s`, 0) = 0 LIMIT 1",
			constants.FieldSysObject_AccessPolicy,
			constants.FieldSysObject_AccessPolicyRecordMutationPackName,
			constants.FieldSysObject_AccessPolicyRecordMutationPackValue,
			constants.FieldSysObject_AccessPolicyLifecyclePackName,
			constants.FieldSysObject_AccessPolicyLifecyclePackValue,
			constants.TableObject,
			constants.FieldSysObject_APIName,
			constants.FieldIsDeleted,
		),
		strings.ToLower(strings.TrimSpace(obj.APIName)),
	).Scan(&liveRaw, &recordMutationPackName, &recordMutationPackValue, &lifecyclePackName, &lifecyclePackValue)
	if err == sql.ErrNoRows {
		return nil
	}
	if err != nil {
		return fmt.Errorf("query live AccessPolicy sidecars: %w", err)
	}

	policy, err := domainschema.PreservePackOwnedAccessPolicySidecars(
		obj.AccessPolicy,
		domainschema.AccessPolicySidecarSnapshot{
			LiveRaw:                 liveRaw,
			RecordMutationPackName:  recordMutationPackName,
			RecordMutationPackValue: recordMutationPackValue,
			LifecyclePackName:       lifecyclePackName,
			LifecyclePackValue:      lifecyclePackValue,
		},
		domainschema.AccessPolicySidecarPreserveOptions{
			ObjectAPIName:          obj.APIName,
			RequireOwnedProjection: true,
		},
	)
	if err != nil {
		return err
	}
	obj.AccessPolicy = policy
	return nil
}
