package bootstrap

import (
	"database/sql"
	"fmt"

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

// ActionFieldDefaultRow is the subset of _System_ActionFieldDefault the
// standard-action dispatcher consumes at request time. The Condition and
// ValueFormula strings are fed to the shared formula engine.
//
// Relocated verbatim to the contract module's seedrows package (Wave 0); this
// alias keeps existing importers compiling unchanged.
type ActionFieldDefaultRow = seedrows.ActionFieldDefaultRow

// GetActionFieldDefaults returns every active default row for a standard
// action Id, sorted by (TargetObject, FieldAPIName, Priority DESC) so
// higher-priority rows win ties within a (TargetObject, FieldAPIName)
// pair after dispatcher deduplication.
func GetActionFieldDefaults(db *sql.DB, standardActionID string) ([]ActionFieldDefaultRow, error) {
	query := fmt.Sprintf(
		`SELECT TargetObject, FieldAPIName, ValueFormula, `+"`Condition`"+`, Priority
		   FROM %s
		  WHERE StandardActionId = ? AND IsActive = 1 AND IsDeleted = 0
		  ORDER BY TargetObject ASC, FieldAPIName ASC, Priority DESC`,
		tableActionFieldDefault,
	)
	rows, err := db.Query(query, standardActionID)
	if err != nil {
		return nil, fmt.Errorf("query action field defaults: %w", err)
	}
	defer rows.Close()

	var out []ActionFieldDefaultRow
	for rows.Next() {
		var row ActionFieldDefaultRow
		var cond sql.NullString
		if err := rows.Scan(&row.TargetObject, &row.FieldAPIName, &row.ValueFormula, &cond, &row.Priority); err != nil {
			return nil, fmt.Errorf("scan action field default row: %w", err)
		}
		if cond.Valid {
			row.Condition = cond.String
		}
		out = append(out, row)
	}
	return out, rows.Err()
}

// GetActionFieldDefaultsForActions returns active default rows for several
// standard-action IDs in one DB round trip, grouped by StandardActionId. Row
// ordering within each group matches GetActionFieldDefaults.
func GetActionFieldDefaultsForActions(db *sql.DB, standardActionIDs []string) (map[string][]ActionFieldDefaultRow, error) {
	actionIDs := uniqueActionIDs(standardActionIDs)
	out := make(map[string][]ActionFieldDefaultRow, len(actionIDs))
	for _, id := range actionIDs {
		out[id] = nil
	}
	if db == nil || len(actionIDs) == 0 {
		return out, nil
	}
	query := fmt.Sprintf(
		`SELECT StandardActionId, TargetObject, FieldAPIName, ValueFormula, `+"`Condition`"+`, Priority
		   FROM %s
		  WHERE StandardActionId IN (%s) AND IsActive = 1 AND IsDeleted = 0
		  ORDER BY StandardActionId ASC, TargetObject ASC, FieldAPIName ASC, Priority DESC`,
		tableActionFieldDefault,
		actionReaderSQLPlaceholders(len(actionIDs)),
	)
	args := make([]interface{}, len(actionIDs))
	for i, id := range actionIDs {
		args[i] = id
	}
	rows, err := db.Query(query, args...)
	if err != nil {
		return nil, fmt.Errorf("query action field defaults batch: %w", err)
	}
	defer rows.Close()

	for rows.Next() {
		var actionID string
		var row ActionFieldDefaultRow
		var cond sql.NullString
		if err := rows.Scan(&actionID, &row.TargetObject, &row.FieldAPIName, &row.ValueFormula, &cond, &row.Priority); err != nil {
			return nil, fmt.Errorf("scan action field default row: %w", err)
		}
		if cond.Valid {
			row.Condition = cond.String
		}
		out[actionID] = append(out[actionID], row)
	}
	return out, rows.Err()
}
