package jenkins

import (
	"github.com/tidbcloud/AgentTeam/internal/extension/registry"
	"github.com/tidbcloud/AgentTeam/internal/extension/spec"
)

const (
	// Domain is the immutable Extension identity shared by the catalog and
	// runtime implementation.
	Domain = "jenkins"

	ActionListJobs        = "list-jobs"
	ActionGetJob          = "get-job"
	ActionTriggerBuild    = "trigger-build"
	ActionGetQueueItem    = "get-queue-item"
	ActionGetBuild        = "get-build"
	ActionGetConsoleLog   = "get-console-log"
	ActionCancelQueueItem = "cancel-queue-item"
	ActionStopBuild       = "stop-build"
)

// Definition returns the Agent-visible Jenkins operational catalog.
func Definition() registry.Definition {
	return registry.Definition{
		Domain:      Domain,
		Version:     1,
		Name:        "Jenkins",
		Description: "Discover Jenkins jobs, trigger and inspect builds, read bounded console output, and stop queued or running work through the configured Jenkins connection.",
		Actions: []registry.DefinitionAction{
			{
				Name:         ActionListJobs,
				Summary:      "List Jenkins jobs",
				Description:  "List jobs at the Jenkins root or directly inside the folder identified by jobPath.",
				Safety:       readSafety(),
				InputSchema:  listJobsInputSchema(),
				OutputSchema: looseJSONObjectSchema("The Jenkins job-list object."),
				Example:      map[string]any{"jobPath": []string{"platform"}},
			},
			{
				Name:         ActionGetJob,
				Summary:      "Get a Jenkins job",
				Description:  "Get the Jenkins Core metadata object for the job identified by jobPath.",
				Safety:       readSafety(),
				InputSchema:  jobInputSchema("The Jenkins job to retrieve."),
				OutputSchema: looseJSONObjectSchema("The Jenkins job metadata object."),
				Example:      map[string]any{"jobPath": []string{"platform", "release"}},
			},
			{
				Name:        ActionTriggerBuild,
				Summary:     "Trigger a Jenkins build",
				Description: "Schedule a build of the job identified by jobPath, optionally supplying scalar build parameters.",
				Safety:      mutationSafety(),
				InputSchema: triggerBuildInputSchema(),
				OutputSchema: objectSchema(
					"The queued Jenkins build.",
					map[string]any{
						"queueId": positiveSafeIntegerSchema(
							"The Jenkins queue item ID assigned to the build."),
					},
					[]string{"queueId"},
				),
				Example: map[string]any{
					"jobPath": []string{"platform", "release"},
					"parameters": map[string]any{
						"BRANCH": "main",
						"DEPLOY": true,
					},
				},
			},
			{
				Name:         ActionGetQueueItem,
				Summary:      "Get a Jenkins queue item",
				Description:  "Get the Jenkins Core queue object for a positive queue item ID.",
				Safety:       readSafety(),
				InputSchema:  queueItemInputSchema(),
				OutputSchema: looseJSONObjectSchema("The Jenkins queue item object."),
				Example:      map[string]any{"queueId": 123},
			},
			{
				Name:         ActionGetBuild,
				Summary:      "Get a Jenkins build",
				Description:  "Get the Jenkins Core build object for a job and positive build number.",
				Safety:       readSafety(),
				InputSchema:  numberedBuildInputSchema(),
				OutputSchema: looseJSONObjectSchema("The Jenkins build object."),
				Example: map[string]any{
					"jobPath":     []string{"platform", "release"},
					"buildNumber": 42,
				},
			},
			{
				Name:         ActionGetConsoleLog,
				Summary:      "Get Jenkins console output",
				Description:  "Read one bounded progressive console-log chunk for a job build, starting at the requested byte offset.",
				Safety:       readSafety(),
				InputSchema:  consoleLogInputSchema(),
				OutputSchema: consoleLogOutputSchema(),
				Example: map[string]any{
					"jobPath":     []string{"platform", "release"},
					"buildNumber": 42,
					"start":       0,
				},
			},
			{
				Name:         ActionCancelQueueItem,
				Summary:      "Cancel a Jenkins queue item",
				Description:  "Remove the identified item from the Jenkins build queue before it starts.",
				Safety:       destructiveSafety(),
				InputSchema:  queueItemInputSchema(),
				OutputSchema: acknowledgementOutputSchema("cancelled"),
				Example:      map[string]any{"queueId": 123},
			},
			{
				Name:         ActionStopBuild,
				Summary:      "Stop a Jenkins build",
				Description:  "Request an ordinary Jenkins stop for the running build identified by jobPath and buildNumber.",
				Safety:       destructiveSafety(),
				InputSchema:  numberedBuildInputSchema(),
				OutputSchema: acknowledgementOutputSchema("stopped"),
				Example: map[string]any{
					"jobPath":     []string{"platform", "release"},
					"buildNumber": 42,
				},
			},
		},
	}
}

func readSafety() spec.Safety {
	return spec.Safety{
		Class:       "read",
		Idempotent:  true,
		Destructive: false,
	}
}

func mutationSafety() spec.Safety {
	return spec.Safety{
		Class:       "mutation",
		Idempotent:  false,
		Destructive: false,
	}
}

func destructiveSafety() spec.Safety {
	return spec.Safety{
		Class:       "destructive",
		Idempotent:  true,
		Destructive: true,
	}
}
