package tools

// ── Built-in Predicates (v0.25.0) ──────────
//
// Predicates determine tool availability based on runtime context.
// Tools declare their availability by returning a Require from
// Availability(). The registry evaluates predicates in AvailableFor()
// before sending tool definitions to the LLM.
//
// AlwaysAvailable is defined in types.go (BaseTool references it).

// RequireWorkspace returns true when a workspace is bound to the
// channel. Workspace and git tools use this.
func RequireWorkspace(tc ToolContext) bool {
	return tc.WorkspaceID != ""
}

// RequireWorkflow returns true when the channel is a workflow instance.
// Workflow-specific tools (e.g. workflow_advance) use this.
func RequireWorkflow(tc ToolContext) bool {
	return tc.WorkflowID != ""
}

// RequireTeam returns true when the channel belongs to a team.
func RequireTeam(tc ToolContext) bool {
	return tc.TeamID != ""
}

// DenyVisitor returns true for authenticated users, false for anonymous
// session participants (v0.24.3). Tools that expose personal data
// (memory, notes) or perform privileged operations use this.
func DenyVisitor(tc ToolContext) bool {
	return !tc.IsVisitor
}

// All combines multiple predicates — all must pass for the tool to be
// available. Short-circuits on first failure.
func All(reqs ...Require) Require {
	return func(tc ToolContext) bool {
		for _, r := range reqs {
			if !r(tc) {
				return false
			}
		}
		return true
	}
}

// Any combines multiple predicates — at least one must pass.
// Short-circuits on first success.
func Any(reqs ...Require) Require {
	return func(tc ToolContext) bool {
		for _, r := range reqs {
			if r(tc) {
				return true
			}
		}
		return false
	}
}

// Not inverts a predicate.
func Not(req Require) Require {
	return func(tc ToolContext) bool {
		return !req(tc)
	}
}

// ── Shared Base Types ───────────────────────
// Embedded in tool structs to provide common availability predicates
// without repeating Availability() overrides on every struct.

// workspaceToolBase provides RequireWorkspace + DenyVisitor availability.
// Embed in workspace and git tool structs.
type workspaceToolBase struct{ BaseTool }

var _requireWorkspaceAndDenyVisitor = All(RequireWorkspace, DenyVisitor)

func (workspaceToolBase) Availability() Require { return _requireWorkspaceAndDenyVisitor }

// visitorDeniedBase provides DenyVisitor availability.
// Embed in memory and notes tool structs.
type visitorDeniedBase struct{ BaseTool }

func (visitorDeniedBase) Availability() Require { return DenyVisitor }
