package packs

import (
	"context"
	"database/sql"

	"github.com/nexuscrm/analytics"
	"github.com/nexuscrm/automation/autonumber"
	"github.com/nexuscrm/db"
	"github.com/nexuscrm/kernel/pkg/ports"
	"github.com/nexuscrm/metadata"
	"github.com/nexuscrm/permissions"
	"github.com/nexuscrm/shared/pkg/models"
)

type ApplyOptions struct {
	SkipPolymorphicDiscriminatorBackfill bool
	// RepairLegacyUniqueDuplicates is an explicit operator repair mode for
	// historical rows that duplicated object_spec unique values before that
	// contract was enforced. It clears duplicate non-canonical values only when
	// the target physical column is nullable and owned by object_spec apply.
	RepairLegacyUniqueDuplicates bool
	// DeferFormulaViewRebuild mirrors the control-plane apply option of the
	// same name onto the pack apply path: pack materialization neither
	// replaces nor creates formula views — existing views are skipped
	// (replacement belongs to the deployment's activation window) and a
	// missing view fails closed (cutover releases must not introduce
	// active-formula objects).
	DeferFormulaViewRebuild bool
}

// SystemAdmin is the system-management surface the pack apply path invokes
// (profiles/users/passwords/connected-app upserts). It is declared by the
// consumer (this package) so packs do not depend on the backend composition
// root's application service package; the composition root's SystemManager
// satisfies it structurally and is injected via ServiceGraph.System().
type SystemAdmin interface {
	BatchUpsertProfiles(ctx context.Context, profiles []models.Profile) error
	BatchUpsertUsers(ctx context.Context, users []models.User) error
	ForceSetUserPassword(ctx context.Context, email, password string) error
	UpsertConnectedApp(ctx context.Context, id, name, consumerKey, consumerSecret string, sessionIssuerClass ...string) error
}

// ApplyDeps provides the services that packs need during apply.
type ApplyDeps struct {
	DB                 *sql.DB
	DBConn             *database.TiDBConnection
	TxManager          ports.TransactionManager
	Metadata           *metadata.MetadataService
	Schema             *metadata.SchemaManager
	Permissions        *permissions.PermissionService
	System             SystemAdmin
	FormulaView        *analytics.FormulaViewService
	AutoNumberMetadata *autonumber.MetadataSource
	MetadataRepo       ports.MetadataRepository
	SessionRepo        ports.SessionRepository
	ConnectedAppHook   ports.ConnectedAppInvalidationHook
	Options            ApplyOptions
}

// VerifyDeps provides read-only access for pack verification.
//
// DeepChecks signals an operator-initiated verify (`cmd/setup verify`)
// where gates that scan live object tables or assume writer quiescence
// are appropriate. The default (false) is the pod-readiness contract:
// cheap, metadata-only checks that are safe to run on every restart
// and tolerant of concurrent writers.
type VerifyDeps struct {
	DB         *sql.DB
	DeepChecks bool
}
