package constants

import "strings"

const (
	FlowScheduleFrequencyOnce   = "Once"
	FlowScheduleFrequencyDaily  = "Daily"
	FlowScheduleFrequencyWeekly = "Weekly"
)

type flowScheduleFrequencySpec struct {
	Canonical     string
	OccurrenceKey string
}

var flowScheduleFrequencySpecs = []flowScheduleFrequencySpec{
	{Canonical: FlowScheduleFrequencyOnce, OccurrenceKey: "once"},
	{Canonical: FlowScheduleFrequencyDaily, OccurrenceKey: "daily"},
	{Canonical: FlowScheduleFrequencyWeekly, OccurrenceKey: "weekly"},
}

func NormalizeFlowScheduleFrequency(raw string) (string, bool) {
	raw = strings.TrimSpace(raw)
	for _, spec := range flowScheduleFrequencySpecs {
		if strings.EqualFold(raw, spec.Canonical) {
			return spec.Canonical, true
		}
	}
	return raw, false
}

func FlowScheduleOccurrenceKey(frequency string) (string, bool) {
	canonical, ok := NormalizeFlowScheduleFrequency(frequency)
	if !ok {
		return "", false
	}
	for _, spec := range flowScheduleFrequencySpecs {
		if spec.Canonical == canonical {
			return spec.OccurrenceKey, true
		}
	}
	return "", false
}

const (
	ApprovalModeFirstResponse = "FirstResponse"
	ApprovalModeUnanimous     = "Unanimous"
)

func NormalizeApprovalMode(raw string) string {
	if strings.EqualFold(strings.TrimSpace(raw), ApprovalModeUnanimous) {
		return ApprovalModeUnanimous
	}
	return ApprovalModeFirstResponse
}

const (
	ApprovalRejectBehaviorBackToPrevious  = "BackToPrevious"
	ApprovalRejectBehaviorBackToSubmitter = "BackToSubmitter"
	ApprovalRejectBehaviorRejectRequest   = "RejectRequest"
	ApprovalRejectBehaviorFinalRejection  = "FinalRejection"
)

func NormalizeApprovalRejectBehavior(raw string) string {
	switch strings.ToLower(strings.TrimSpace(raw)) {
	case "backtoprevious":
		return ApprovalRejectBehaviorBackToPrevious
	case "backtosubmitter":
		return ApprovalRejectBehaviorBackToSubmitter
	case "rejectrequest":
		return ApprovalRejectBehaviorRejectRequest
	case "finalrejection":
		return ApprovalRejectBehaviorFinalRejection
	default:
		return strings.TrimSpace(raw)
	}
}

func NormalizeApprovalProcessNodeRejectBehavior(raw string) string {
	switch NormalizeApprovalRejectBehavior(raw) {
	case ApprovalRejectBehaviorBackToPrevious:
		return ApprovalRejectBehaviorBackToSubmitter
	case ApprovalRejectBehaviorRejectRequest, "":
		return ApprovalRejectBehaviorFinalRejection
	default:
		return NormalizeApprovalRejectBehavior(raw)
	}
}

const (
	ApprovalActionEventSubmit         = "Submit"
	ApprovalActionEventStepApproval   = "StepApproval"
	ApprovalActionEventStepRejection  = "StepRejection"
	ApprovalActionEventFinalApproval  = "FinalApproval"
	ApprovalActionEventFinalRejection = "FinalRejection"
	ApprovalActionEventRecall         = "Recall"
	ApprovalActionEventReassign       = "Reassign"
)

const (
	ApprovalApproverTypeRelatedUserField   = "relatedUserField"
	ApprovalApproverTypeUserHierarchyField = "userHierarchyField"
	ApprovalApproverTypePreviousApprover   = "previousApprover"
	ApprovalApproverTypeAdhoc              = "adhoc"
	ApprovalApproverTypeUser               = "user"
	ApprovalApproverTypeQueue              = "queue"
	ApprovalApproverTypeRole               = "role"
	ApprovalApproverTypeHierarchy          = "hierarchy"
)

func NormalizeApprovalApproverType(raw string) string {
	switch strings.ToLower(strings.TrimSpace(raw)) {
	case "relateduser", "relateduserfield":
		return ApprovalApproverTypeRelatedUserField
	case "userhierarchyfield":
		return ApprovalApproverTypeUserHierarchyField
	case "previousapprover":
		return ApprovalApproverTypePreviousApprover
	case "adhoc":
		return ApprovalApproverTypeAdhoc
	case "user":
		return ApprovalApproverTypeUser
	case "queue":
		return ApprovalApproverTypeQueue
	case "role":
		return ApprovalApproverTypeRole
	case "hierarchy":
		return ApprovalApproverTypeHierarchy
	default:
		return strings.TrimSpace(raw)
	}
}

const (
	ApprovalSubmitterTypeAllInternalUsers    = "allInternalUsers"
	ApprovalSubmitterTypeRecordCreator       = "recordCreator"
	ApprovalSubmitterTypeRecordOwner         = "recordOwner"
	ApprovalSubmitterTypeUser                = "user"
	ApprovalSubmitterTypeRole                = "role"
	ApprovalSubmitterTypeRoleAndSubordinates = "roleAndSubordinates"
)

func NormalizeApprovalSubmitterType(raw string) string {
	switch strings.ToLower(strings.TrimSpace(raw)) {
	case "allinternalusers":
		return ApprovalSubmitterTypeAllInternalUsers
	case "recordcreator", "creator":
		return ApprovalSubmitterTypeRecordCreator
	case "recordowner", "owner":
		return ApprovalSubmitterTypeRecordOwner
	case "user":
		return ApprovalSubmitterTypeUser
	case "role":
		return ApprovalSubmitterTypeRole
	case "roleandsubordinates", "hierarchy":
		return ApprovalSubmitterTypeRoleAndSubordinates
	default:
		return strings.TrimSpace(raw)
	}
}

const (
	GroupTypeQueue               = "Queue"
	GroupTypeRole                = "Role"
	GroupTypeRoleAndSubordinates = "RoleAndSubordinates"
)

func IsRoleBackedGroupType(groupType string) bool {
	switch {
	case strings.EqualFold(strings.TrimSpace(groupType), GroupTypeRole):
		return true
	case strings.EqualFold(strings.TrimSpace(groupType), GroupTypeRoleAndSubordinates):
		return true
	default:
		return false
	}
}

func GroupTypeIncludesSubordinateRoles(groupType string) bool {
	return strings.EqualFold(strings.TrimSpace(groupType), GroupTypeRoleAndSubordinates)
}

const (
	TabVisibilityDefaultOn  = "DefaultOn"
	TabVisibilityVisible    = "Visible"
	TabVisibilityDefaultOff = "DefaultOff"
	TabVisibilityAvailable  = "Available"
	TabVisibilityHidden     = "Hidden"
	TabVisibilityNone       = "None"
)

type TabVisibilityRankEntry struct {
	Visibility string
	Rank       int
}

var tabVisibilityRankEntries = []TabVisibilityRankEntry{
	{Visibility: TabVisibilityDefaultOn, Rank: 3},
	{Visibility: TabVisibilityVisible, Rank: 3},
	{Visibility: TabVisibilityDefaultOff, Rank: 2},
	{Visibility: TabVisibilityAvailable, Rank: 2},
	{Visibility: TabVisibilityHidden, Rank: 1},
	{Visibility: TabVisibilityNone, Rank: 1},
}

func TabVisibilityRankEntries() []TabVisibilityRankEntry {
	out := make([]TabVisibilityRankEntry, len(tabVisibilityRankEntries))
	copy(out, tabVisibilityRankEntries)
	return out
}

func TabVisibilityRank(visibility string) int {
	for _, entry := range tabVisibilityRankEntries {
		if strings.EqualFold(strings.TrimSpace(visibility), entry.Visibility) {
			return entry.Rank
		}
	}
	return 0
}

func TabVisibilityFromRank(rank int) string {
	switch rank {
	case 3:
		return TabVisibilityDefaultOn
	case 2:
		return TabVisibilityDefaultOff
	case 1:
		return TabVisibilityHidden
	default:
		return ""
	}
}

var systemRelatedObjectExactNames = map[string]struct{}{
	"openactivity":                {},
	"activityhistory":             {},
	"processinstancehistory":      {},
	"eventwhorelation":            {},
	"eventrelation":               {},
	"acceptedeventrelation":       {},
	"declinedeventrelation":       {},
	"undecidedeventrelation":      {},
	"taskwhorelation":             {},
	"taskrelation":                {},
	"objectterritory2association": {},
	"userrole":                    {},
	"attachment":                  {},
}

var systemRelatedObjectSuffixes = []string{
	"share",
	"feed",
	"history",
	"changeevent",
	"fieldhistory",
}

func IsSystemRelatedObjectAPIName(apiName string) bool {
	lower := strings.ToLower(strings.TrimSpace(apiName))
	if _, ok := systemRelatedObjectExactNames[lower]; ok {
		return true
	}
	for _, suffix := range systemRelatedObjectSuffixes {
		if strings.HasSuffix(lower, suffix) {
			return true
		}
	}
	return false
}
