package bootstrap

import (
	"database/sql"
	"fmt"
	"strconv"
	"strings"
)

// ActionSchemaRow is the subset of _System_ActionSchema consumed by the
// generic standard-action dispatcher at request time.
type ActionSchemaRow struct {
	Direction           string
	APIName             string
	DataType            string
	ReferenceTo         string
	Label               string
	UISection           string
	UIMode              string
	TargetObject        string
	TargetFieldAPIName  string
	RequiredPicklistTag string
	MappingSourceObject string
	MappingActionType   string
	IsRequired          bool
	SortOrder           int
}

// GetActionSchema returns every active input/output descriptor for a
// standard-action Id, sorted by (Direction, SortOrder, APIName).
func GetActionSchema(db *sql.DB, standardActionID string) ([]ActionSchemaRow, error) {
	query := fmt.Sprintf(
		`SELECT Direction, APIName, DataType, ReferenceTo, Label, UISection, UIMode,
		        TargetObject, TargetFieldAPIName, RequiredPicklistTag, MappingSourceObject, MappingActionType,
		        IsRequired, SortOrder
		   FROM %s
		  WHERE StandardActionId = ? AND IsActive = 1 AND IsDeleted = 0
		  ORDER BY Direction ASC, SortOrder ASC, APIName ASC`,
		tableActionSchema,
	)
	rows, err := db.Query(query, standardActionID)
	if err != nil {
		return nil, fmt.Errorf("query action schema: %w", err)
	}
	defer rows.Close()

	cols, err := rows.Columns()
	if err != nil {
		return nil, fmt.Errorf("read action schema columns: %w", err)
	}

	var out []ActionSchemaRow
	for rows.Next() {
		var row ActionSchemaRow
		values := make([]sql.NullString, len(cols))
		scanArgs := make([]interface{}, len(cols))
		for i := range values {
			scanArgs[i] = &values[i]
		}
		if err := rows.Scan(scanArgs...); err != nil {
			return nil, fmt.Errorf("scan action schema row: %w", err)
		}
		for i, col := range cols {
			if !values[i].Valid {
				continue
			}
			assignActionSchemaColumn(&row, col, values[i].String)
		}
		out = append(out, row)
	}
	return out, rows.Err()
}

func assignActionSchemaColumn(row *ActionSchemaRow, col string, value string) {
	switch strings.ToLower(col) {
	case "direction":
		row.Direction = value
	case "apiname":
		row.APIName = value
	case "datatype":
		row.DataType = value
	case "referenceto":
		row.ReferenceTo = value
	case "label":
		row.Label = value
	case "uisection":
		row.UISection = value
	case "uimode":
		row.UIMode = value
	case "targetobject":
		row.TargetObject = value
	case "targetfieldapiname":
		row.TargetFieldAPIName = value
	case "requiredpicklisttag":
		row.RequiredPicklistTag = value
	case "mappingsourceobject":
		row.MappingSourceObject = value
	case "mappingactiontype":
		row.MappingActionType = value
	case "isrequired":
		row.IsRequired = value == "1" || strings.EqualFold(value, "true")
	case "sortorder":
		if n, err := strconv.Atoi(value); err == nil {
			row.SortOrder = n
		}
	}
}
