package bootstrapimpl

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"regexp"
	"strings"

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

// --- Metadata/Schema Assertions ---

// assertObjectTableMapping verifies that every Object metadata entry has a corresponding DB table
func assertObjectTableMapping(db *sql.DB, result *AssertionResult) {
	log.Println("   📋 Checking object-table mapping verification...")

	// 1. Get all objects and their physical read targets from metadata.
	objSQL := fmt.Sprintf("SELECT `%s`, `%s` FROM `%s`", constants.FieldAPIName, constants.FieldSysObject_ReadSource, constants.TableObject)
	rows, err := db.Query(objSQL)
	if err != nil {
		log.Printf("   ⚠️  Could not query objects: %v", err)
		return
	}
	defer rows.Close()

	type objectTableMapping struct {
		logicalName  string
		physicalName string
	}
	var objectMappings []objectTableMapping
	for rows.Next() {
		var name string
		var readSource sql.NullString
		if err := rows.Scan(&name, &readSource); err != nil {
			continue
		}
		physicalName, err := assertionPhysicalTableName(name, readSource)
		if err != nil {
			result.Violations = append(result.Violations, AssertionViolation{
				Category:    "SchemaMismatch",
				Severity:    constants.SeverityError,
				Object:      name,
				Description: fmt.Sprintf("Object '%s' has invalid ReadSource metadata: %v", name, err),
			})
			continue
		}
		objectMappings = append(objectMappings, objectTableMapping{logicalName: name, physicalName: physicalName})
	}
	if err := rows.Err(); err != nil {
		log.Printf("   ⚠️  Error iterating objects: %v", err)
		return
	}

	// 2. Get all actual tables in one query.
	// Keys are lowercased because TiDB's lower_case_table_names=2 stores table names
	// as-created but compares case-insensitively; metadata ApiName casing may not
	// match physical table casing (e.g. "ExampleObject" vs "exampleobject").
	actualTables := make(map[string]bool)
	tRows, err := db.Query("SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE()")
	if err != nil {
		log.Printf("   ⚠️  Could not query information_schema.tables: %v", err)
		return
	}
	defer tRows.Close()
	for tRows.Next() {
		var name string
		if err := tRows.Scan(&name); err == nil {
			actualTables[strings.ToLower(name)] = true
		}
	}

	// 3. Diff (case-insensitive, matching TiDB resolution semantics)
	for _, mapping := range objectMappings {
		if !actualTables[strings.ToLower(mapping.physicalName)] {
			result.Violations = append(result.Violations, AssertionViolation{
				Category:    "SchemaMismatch",
				Severity:    constants.SeverityError,
				Object:      mapping.logicalName,
				Description: fmt.Sprintf("Metadata exists for object '%s', but its physical read table '%s' is missing.", mapping.logicalName, mapping.physicalName),
			})
		}
	}
}

// assertFieldColumnMapping verifies that every physical metadata field has a corresponding column.
// Uses two bulk queries (all fields + all columns) instead of per-object queries to avoid N+1.
func assertFieldColumnMapping(db *sql.DB, result *AssertionResult) {
	log.Println("   📋 Checking field-column mapping verification...")

	// 1. Bulk load all fields with their object names (single query)
	fieldSQL := fmt.Sprintf(
		"SELECT o.`%s`, o.`%s`, f.`%s`, f.`%s` FROM `%s` f JOIN `%s` o ON f.`%s` = o.`%s` "+
			"WHERE f.`%s` = 0 AND NOT (LOWER(TRIM(COALESCE(f.`%s`, ''))) = 'active' "+
			"AND (TRIM(COALESCE(f.`%s`, '')) != '' OR TRIM(COALESCE(f.`%s`, '')) != ''))",
		constants.FieldAPIName, constants.FieldSysObject_ReadSource, constants.FieldAPIName, constants.FieldSysField_PhysicalName,
		constants.TableField, constants.TableObject,
		constants.FieldObjectID, constants.ColID,
		constants.FieldIsDeleted,
		constants.FieldSysField_FormulaMode,
		constants.FieldSysField_Formula,
		constants.FieldSysField_ProjectionConfig,
	)

	fieldRows, err := db.Query(fieldSQL)
	if err != nil {
		log.Printf("   ⚠️  Could not bulk-query fields: %v", err)
		return
	}
	defer fieldRows.Close()

	// expectedCols[lowerTableName] = set of expected column names (lowercased).
	// Both table and column keys are lowercased to match TiDB's case-insensitive
	// name resolution (lower_case_table_names=2) — avoids false positives where
	// metadata and physical schema only differ in casing.
	expectedCols := make(map[string]map[string]bool)
	// Keep original object name for error reporting
	objNameByLower := make(map[string]string)
	invalidReadSources := make(map[string]bool)
	for fieldRows.Next() {
		var objName, apiName string
		var readSource, physicalName sql.NullString
		if err := fieldRows.Scan(&objName, &readSource, &apiName, &physicalName); err != nil {
			continue
		}
		physicalTableName, err := assertionPhysicalTableName(objName, readSource)
		if err != nil {
			if !invalidReadSources[strings.ToLower(objName)] {
				result.Violations = append(result.Violations, AssertionViolation{
					Category:    "SchemaMismatch",
					Severity:    constants.SeverityError,
					Object:      objName,
					Description: fmt.Sprintf("Object '%s' has invalid ReadSource metadata: %v", objName, err),
				})
				invalidReadSources[strings.ToLower(objName)] = true
			}
			continue
		}
		colName := apiName
		if physicalName.Valid {
			candidate := strings.TrimSpace(physicalName.String)
			if !(strings.HasPrefix(candidate, "`") && strings.HasSuffix(candidate, "`")) && candidate != "" {
				colName = candidate
			}
		}
		lowerTable := strings.ToLower(physicalTableName)
		if expectedCols[lowerTable] == nil {
			expectedCols[lowerTable] = make(map[string]bool)
		}
		expectedCols[lowerTable][strings.ToLower(colName)] = true
		if _, ok := objNameByLower[lowerTable]; !ok {
			objNameByLower[lowerTable] = objName
		}
	}
	if err := fieldRows.Err(); err != nil {
		log.Printf("   ⚠️  Error iterating fields: %v", err)
		return
	}

	// 2. Bulk load all columns from information_schema (single query)
	colRows, err := db.Query("SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = DATABASE()")
	if err != nil {
		log.Printf("   ⚠️  Could not bulk-query information_schema.columns: %v", err)
		return
	}
	defer colRows.Close()

	// actualCols[lowerTableName] = set of actual column names (lowercased)
	actualCols := make(map[string]map[string]bool)
	for colRows.Next() {
		var tableName, colName string
		if err := colRows.Scan(&tableName, &colName); err == nil {
			lowerTbl := strings.ToLower(tableName)
			if actualCols[lowerTbl] == nil {
				actualCols[lowerTbl] = make(map[string]bool)
			}
			actualCols[lowerTbl][strings.ToLower(colName)] = true
		}
	}
	if err := colRows.Err(); err != nil {
		log.Printf("   ⚠️  Error iterating columns: %v", err)
		return
	}

	// 3. Diff in memory (case-insensitive)
	for lowerObj, expected := range expectedCols {
		actual := actualCols[lowerObj]
		var missing []string
		for col := range expected {
			if actual == nil || !actual[col] {
				missing = append(missing, col)
			}
		}
		if len(missing) > 0 {
			result.Violations = append(result.Violations, AssertionViolation{
				Category:    "SchemaMismatch",
				Severity:    constants.SeverityError,
				Object:      objNameByLower[lowerObj],
				Description: fmt.Sprintf("Table '%s' is missing physical columns for fields: %s", objNameByLower[lowerObj], strings.Join(missing, ", ")),
			})
		}
	}
}

func assertionPhysicalTableName(logicalName string, readSource sql.NullString) (string, error) {
	if !readSource.Valid || strings.TrimSpace(readSource.String) == "" {
		return logicalName, nil
	}
	var config models.ObjectReadSourceConfig
	if err := json.Unmarshal([]byte(readSource.String), &config); err != nil {
		return "", err
	}
	metadata := &models.ObjectMetadata{APIName: logicalName, ReadSource: &config}
	return metadata.ResolveReadSourceTable()
}

// assertLookupReferenceTargetsPopulated verifies that bootstrap-owned active
// lookup fields on active objects have explicit ReferenceTo metadata. L0
// managed definitions and platform-universal fields are checked here; pack,
// admin, and discovery-owned metadata are verified by their owning surfaces.
func assertLookupReferenceTargetsPopulated(db *sql.DB, result *AssertionResult) {
	log.Println("   📋 Checking lookup ReferenceTo metadata...")
	repairTargets := LookupReferenceRepairTargets()

	query := fmt.Sprintf(
		"SELECT o.`%s`, f.`%s`, f.`%s`, f.`%s` FROM `%s` f JOIN `%s` o ON f.`%s` = o.`%s` "+
			"WHERE f.`%s` IN (?, ?) AND COALESCE(f.`%s`, 0) = 0 AND COALESCE(o.`%s`, 0) = 0 "+
			"AND (f.`%s` IS NULL OR TRIM(f.`%s`) = '' OR TRIM(f.`%s`) = '[]')",
		constants.FieldAPIName, constants.FieldAPIName, constants.FieldType, constants.FieldReferenceTo,
		constants.TableField, constants.TableObject,
		constants.FieldObjectID, constants.ColID,
		constants.FieldType, constants.FieldIsDeleted, constants.FieldIsDeleted,
		constants.FieldReferenceTo, constants.FieldReferenceTo, constants.FieldReferenceTo,
	)

	rows, err := db.Query(query, constants.FieldTypeReference, constants.FieldTypeMasterDetail)
	if err != nil {
		log.Printf("   ⚠️  Could not query lookup ReferenceTo metadata: %v", err)
		return
	}
	defer rows.Close()

	for rows.Next() {
		var objName, fieldName, fieldType string
		var referenceTo sql.NullString
		if err := rows.Scan(&objName, &fieldName, &fieldType, &referenceTo); err != nil {
			log.Printf("   ⚠️  Could not scan lookup ReferenceTo row: %v", err)
			continue
		}
		if _, inScope := repairTargets.ReferenceTo(objName, fieldName); !inScope {
			continue
		}

		value := "NULL"
		if referenceTo.Valid {
			value = referenceTo.String
		}
		result.Violations = append(result.Violations, AssertionViolation{
			Category:    "MissingReferenceTo",
			Severity:    constants.SeverityError,
			Object:      objName,
			Description: fmt.Sprintf("Lookup field '%s' (type=%s) has empty ReferenceTo metadata: %s", fieldName, fieldType, value),
		})
	}
	if err := rows.Err(); err != nil {
		log.Printf("   ⚠️  Error iterating lookup ReferenceTo rows: %v", err)
	}
}

// assertRelationshipIntegrity ensures Lookup/MasterDetail fields point to valid objects.
//
// Only fields that are explicitly declared in the managed schema (system_tables.json
// + standard_objects.json via GetManagedTableDefinitions) are checked. Fields
// imported via Salesforce sync or discovery are skipped because they reference
// SF standard objects (e.g. ExternalDataSource, Calendar, Individual, BrandTemplate,
// CallCenter, FlowOrchestrationInstance, etc.) that NexusCRM does not implement.
// Those references are dangling foreign keys with no enforcement at the DB level
// (VARCHAR columns, no FK constraint), and runtime queries don't traverse them
// because the target tables don't exist.
//
// This mirrors the same whitelist principle used by assertSystemFieldsConsistency:
// the assertion's job is to verify the schemas NexusCRM owns, not the schemas it
// merely mirrors from Salesforce.
func assertRelationshipIntegrity(db *sql.DB, result *AssertionResult) {
	log.Println("   📋 Checking relationship integrity...")

	// Build the managed-fields whitelist: parent table -> set of declared field ApiNames.
	// Both keys are lowercased to match TiDB's case-insensitive name resolution.
	managedFields := make(map[string]map[string]bool)
	for _, def := range GetManagedTableDefinitions() {
		parent := strings.ToLower(def.TableName)
		if managedFields[parent] == nil {
			managedFields[parent] = make(map[string]bool)
		}
		for _, col := range def.Columns {
			managedFields[parent][strings.ToLower(col.Name)] = true
		}
	}

	// Get all object API names for validation
	objSQL := fmt.Sprintf("SELECT `%s` FROM `%s`", constants.FieldAPIName, constants.TableObject)
	rows, err := db.Query(objSQL)
	if err != nil {
		log.Printf("   ⚠️  Could not query objects: %v", err)
		return
	}
	defer rows.Close()
	validObjects := make(map[string]bool)
	for rows.Next() {
		var name string
		if err := rows.Scan(&name); err != nil {
			continue
		}
		validObjects[strings.ToLower(name)] = true
	}
	if err := rows.Err(); err != nil {
		log.Printf("   ⚠️  Error iterating objects: %v", err)
	}

	// Check Lookup/MasterDetail fields
	refSQL := fmt.Sprintf(
		"SELECT o.`%s`, f.`%s`, f.`%s`, f.`%s` FROM `%s` f JOIN `%s` o ON f.`%s` = o.`%s` WHERE f.`%s` IN (?, ?) AND f.`%s` = 0",
		constants.FieldAPIName, constants.FieldAPIName, constants.FieldReferenceTo, constants.FieldType,
		constants.TableField, constants.TableObject,
		constants.FieldObjectID, constants.ColID,
		constants.FieldType,
		constants.FieldIsDeleted,
	)

	fRows, err := db.Query(refSQL, constants.FieldTypeReference, constants.FieldTypeMasterDetail)
	if err != nil {
		log.Printf("   ⚠️  Could not query fields: %v", err)
		return
	}
	defer func() { fRows.Close() }()

	for fRows.Next() {
		var objName, fieldName, refToJSON, fType string
		if err := fRows.Scan(&objName, &fieldName, &refToJSON, &fType); err != nil {
			continue
		}

		// Whitelist: only validate fields that are explicitly declared in the
		// managed schema definitions. SF-imported and discovered fields are skipped.
		parentLower := strings.ToLower(objName)
		fieldLower := strings.ToLower(fieldName)
		if managedFields[parentLower] == nil || !managedFields[parentLower][fieldLower] {
			continue
		}

		// reference_to is stored as JSON array
		if strings.HasPrefix(refToJSON, "[") {
			refs := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(refToJSON, "[", ""), "]", ""), "\"", "")
			targets := strings.Split(refs, ",")
			for _, target := range targets {
				target = strings.TrimSpace(target)
				if target != "" && !validObjects[strings.ToLower(target)] {
					result.Violations = append(result.Violations, AssertionViolation{
						Category:    "BrokenRelationship",
						Severity:    constants.SeverityError,
						Object:      objName,
						Description: fmt.Sprintf("Field '%s' references non-existent object '%s'", fieldName, target),
					})
				}
			}
		} else {
			// Invalid format - should be JSON array
			result.Violations = append(result.Violations, AssertionViolation{
				Category:    "InvalidFormat",
				Severity:    constants.SeverityError,
				Object:      objName,
				Description: fmt.Sprintf("Field '%s' has invalid reference_to format (expected JSON array): %s", fieldName, refToJSON),
			})
		}
	}
	if err := fRows.Err(); err != nil {
		log.Printf("   ⚠️  Error iterating relationship fields: %v", err)
	}
}

// assertConstraintConsistency checks if is_unique fields have actual DB indexes.
// Uses a bulk query for statistics instead of per-field queries to avoid N+1.
func assertConstraintConsistency(db *sql.DB, result *AssertionResult) {
	log.Println("   📋 Checking uniqueness constraints...")

	// 1. Get all fields marked unique
	uniqueSQL := fmt.Sprintf(
		"SELECT o.`%s`, f.`%s` FROM `%s` f JOIN `%s` o ON f.`%s` = o.`%s` WHERE f.`%s` = 1 AND f.`%s` = 0",
		constants.FieldAPIName, constants.FieldAPIName,
		constants.TableField, constants.TableObject,
		constants.FieldObjectID, constants.ColID,
		constants.FieldSysField_IsUnique,
		constants.FieldIsDeleted,
	)

	rows, err := db.Query(uniqueSQL)
	if err != nil {
		log.Printf("   ⚠️  Could not query unique fields: %v", err)
		return
	}
	defer rows.Close()

	type uniqueField struct{ Table, Column string }
	var fields []uniqueField
	for rows.Next() {
		var f uniqueField
		if err := rows.Scan(&f.Table, &f.Column); err == nil {
			fields = append(fields, f)
		}
	}
	if err := rows.Err(); err != nil {
		log.Printf("   ⚠️  Error iterating unique fields: %v", err)
		return
	}

	if len(fields) == 0 {
		return
	}

	// 2. Bulk load all unique indexes (single query)
	// Key: "table:column" -> has unique index
	uniqueIndexes := make(map[string]bool)
	idxRows, err := db.Query(`
		SELECT table_name, column_name FROM information_schema.statistics
		WHERE table_schema = DATABASE() AND non_unique = 0
	`)
	if err != nil {
		log.Printf("   ⚠️  Could not bulk-query statistics: %v", err)
		return
	}
	defer idxRows.Close()
	for idxRows.Next() {
		var tbl, col string
		if err := idxRows.Scan(&tbl, &col); err == nil {
			uniqueIndexes[tbl+":"+col] = true
		}
	}

	// 3. Diff in memory
	for _, f := range fields {
		if !uniqueIndexes[f.Table+":"+f.Column] {
			result.Violations = append(result.Violations, AssertionViolation{
				Category:    "MissingConstraint",
				Severity:    constants.SeverityWarning,
				Object:      f.Table,
				Description: fmt.Sprintf("Field '%s' is marked unique but has no unique index in DB.", f.Column),
			})
		}
	}
}

// assertNamingConventions enforces snake_case for all API names
func assertNamingConventions(db *sql.DB, result *AssertionResult) {
	log.Println("   📋 Checking naming conventions...")

	validName := regexp.MustCompile(`^[a-z][a-z0-9_]*$`)

	// Check Objects
	objNamingSQL := fmt.Sprintf(
		"SELECT `%s` FROM `%s` WHERE `%s` = 1 AND `%s` = 0",
		constants.FieldAPIName, constants.TableObject,
		constants.FieldIsCustom, constants.FieldIsDeleted,
	)

	rows, err := db.Query(objNamingSQL)
	if err == nil {
		for rows.Next() {
			var name string
			if err := rows.Scan(&name); err != nil {
				continue
			}
			if !validName.MatchString(name) {
				result.Violations = append(result.Violations, AssertionViolation{
					Category:    "NamingConvention",
					Severity:    constants.SeverityWarning,
					Object:      name,
					Description: fmt.Sprintf("Object API name '%s' should be snake_case (lowercase entry starting with letter).", name),
				})
			}
		}
		if err := rows.Err(); err != nil {
			log.Printf("   ⚠️  Error iterating objects: %v", err)
		}
		rows.Close()
	}

	// Check Fields
	// _System_Field does not have an IsCustom column. Treat fields as "custom"
	// when they live on a custom object or use the Salesforce-style __c suffix.
	fieldNamingSQL := fmt.Sprintf(
		"SELECT o.`%s`, f.`%s` FROM `%s` f JOIN `%s` o ON f.`%s` = o.`%s` "+
			"WHERE (o.`%s` = 1 OR LOWER(f.`%s`) REGEXP '__c$') AND f.`%s` = 0",
		constants.FieldAPIName, constants.FieldAPIName,
		constants.TableField, constants.TableObject,
		constants.FieldObjectID, constants.ColID,
		constants.FieldSysObject_IsCustom, constants.FieldAPIName,
		constants.FieldIsDeleted,
	)

	fRows, err := db.Query(fieldNamingSQL)
	if err == nil {
		for fRows.Next() {
			var objName, fieldName string
			if err := fRows.Scan(&objName, &fieldName); err != nil {
				continue
			}
			if !validName.MatchString(fieldName) {
				result.Violations = append(result.Violations, AssertionViolation{
					Category:    "NamingConvention",
					Severity:    constants.SeverityWarning,
					Object:      objName,
					Description: fmt.Sprintf("Custom field '%s' should be snake_case.", fieldName),
				})
			}
		}
		if err := fRows.Err(); err != nil {
			log.Printf("   ⚠️  Error iterating custom fields: %v", err)
		}
		fRows.Close()
	}
}

// assertFormulaValidity checks if frozen-mode formula expressions can be parsed.
//
// This check runs by default during bootstrap assertions. Issue #301 removed
// the old bootstrap opt-in gate at this call-site; this function now delegates
// unconditionally to validateFrozenFormulasScoped, which uses the fail-closed
// substrate redesigned in issue #300.
//
// Scope: only FormulaMode='frozen' rows are checked. This matches the actual
// runtime contract — pkg/formula.Engine is the evaluator for frozen-mode
// formulas (see backend/internal/features/records/formula_compute.go), so
// validating those expressions through the same engine here is the correct
// "two-path consistency" check.
//
// Active-mode formulas are deliberately excluded: they are not consumed by
// pkg/formula.Engine at runtime. They compile to TiDB view SQL via
// backend/internal/features/analytics/formula_dsl_compiler at view-build
// time, and that path is the source of truth for active-mode validation.
//
// Operators can still opt out with DISABLE_FORMULA_VALIDATION=true. Opt-out
// is explicit and shows up in the log so server readiness no longer silently
// implies a check that did not run.
func assertFormulaValidity(db *sql.DB, result *AssertionResult) {
	_, violations, err := validateFrozenFormulasScoped(context.Background(), db)
	result.Violations = append(result.Violations, violations...)
	if err != nil {
		result.Violations = append(result.Violations, AssertionViolation{
			Category:    "FormulaValidationInfraFailure",
			Severity:    constants.SeverityError,
			Description: fmt.Sprintf("Frozen-formula validity check did not complete: %v", err),
		})
	}
}

// validateFrozenFormulasScoped is the shared core of the frozen-formula
// parse-level lint for live metadata readiness only.
//
// Scope rationale: only FormulaMode='frozen' rows are checked. pkg/formula.Engine
// is the runtime evaluator for frozen-mode formulas (see
// backend/internal/features/records/formula_compute.go), so validating those
// expressions through the same engine here is the correct "two-path consistency"
// check. Active-mode formulas are deliberately excluded: they compile to TiDB view
// SQL via backend/internal/features/analytics/formula_dsl_compiler at view-build
// time, and that path is the source of truth for active-mode validation.
//
// Validation surface: pkg/formula.Engine.ValidateSyntax — parse-level only,
// using expr.AllowUndefinedVariables() so identifier references (sibling fields,
// $Record relationship paths, engine builtins) compile through. The runtime
// evaluator (Engine.Evaluate) constructs env per save from the actual record +
// lazy-fetched relations + user session; metadata-lint time has none of those.
//
// Infrastructure failures (query, row scan, rows.Err iteration error) return
// a non-nil error rather than being silently swallowed. Global readiness treats
// them as an explicit assertion failure, not as proof that the check passed.
//
// Operators can opt out with DISABLE_FORMULA_VALIDATION=true. Opt-out is
// explicit and shows up in the log so server readiness no longer silently
// implies a check that did not run.
func validateFrozenFormulasScoped(ctx context.Context, db *sql.DB) (formula.Verdict, []AssertionViolation, error) {
	if os.Getenv("DISABLE_FORMULA_VALIDATION") == "true" {
		log.Println("   📋 Skipping formula validity check (DISABLE_FORMULA_VALIDATION=true)")
		return formula.Verified, nil, nil
	}
	log.Println("   📋 Checking formula validity (frozen-mode, all owners)...")

	engine := formula.NewEngine()

	formulaSQL := fmt.Sprintf(
		"SELECT o.`%s`, f.`%s`, f.`%s` FROM `%s` f JOIN `%s` o ON f.`%s` = o.`%s` "+
			"WHERE f.`%s` IS NOT NULL AND f.`%s` != '' AND f.`%s` = 0 AND f.`%s` = 'frozen'",
		constants.FieldAPIName, constants.FieldAPIName, constants.FieldSysField_Formula,
		constants.TableField, constants.TableObject,
		constants.FieldObjectID, constants.ColID,
		constants.FieldSysField_Formula, constants.FieldSysField_Formula,
		constants.FieldIsDeleted, constants.FieldSysField_FormulaMode,
	)

	rows, err := db.QueryContext(ctx, formulaSQL)
	if err != nil {
		return formula.Unverified, nil, fmt.Errorf("query frozen-mode formulas: %w", err)
	}
	defer rows.Close()

	var violations []AssertionViolation
	for rows.Next() {
		var objName, fieldName, expression string
		if err := rows.Scan(&objName, &fieldName, &expression); err != nil {
			return formula.Unverified, violations, fmt.Errorf("scan frozen-mode formula row: %w", err)
		}

		// Parse-level validity check. ValidateSyntax tolerates undefined
		// identifiers (sibling fields, $Record paths, builtins) because the
		// runtime evaluator resolves them per-record; only genuine syntax
		// errors, unsupported function names, method-call shapes, and arity
		// mismatches surface as violations here.
		if err := engine.ValidateSyntax(expression); err != nil {
			violations = append(violations, AssertionViolation{
				Category:    "InvalidFormula",
				Severity:    constants.SeverityError,
				Object:      objName,
				Description: fmt.Sprintf("Field '%s' has invalid formula: %v", fieldName, err),
			})
		}
	}
	if err := rows.Err(); err != nil {
		return formula.Unverified, violations, fmt.Errorf("iterate frozen-mode formulas: %w", err)
	}
	if len(violations) > 0 {
		return formula.Failed, violations, nil
	}
	return formula.Verified, nil, nil
}
