package exec

import (
	"encoding/json"
	"fmt"
	"strings"
)

// RenderRootHelp returns help for only the Extension-name/Action pairs in this
// immutable Catalog snapshot using the unified Exec command syntax.
func (snapshot ExtensionSnapshot) RenderRootHelp() string {
	var builder strings.Builder
	builder.WriteString("Usage: agentteam exec <extension-name> <action> <json|->\n")
	builder.WriteString(
		"Schemas: agentteam exec <extension-name> <action> --input-schema | --output-schema\n",
	)
	builder.WriteString("\nAuthorized actions:\n")
	for _, domain := range snapshot.Domains() {
		for _, action := range domain.Actions {
			fmt.Fprintf(
				&builder,
				"  %s %s — %s\n",
				domain.ExtensionName,
				action.Name,
				oneLine(action.Summary),
			)
		}
	}
	builder.WriteString(
		"\nRun `agentteam exec <extension-name> <action> --help` for details.\n",
	)
	return builder.String()
}

// RenderDomainHelp returns help for one authorized Extension name.
func (snapshot ExtensionSnapshot) RenderDomainHelp(extensionName string) (string, bool) {
	for _, domain := range snapshot.Domains() {
		if domain.ExtensionName != extensionName {
			continue
		}
		var builder strings.Builder
		fmt.Fprintf(
			&builder,
			"%s — %s\n\nAuthorized actions:\n",
			extensionName,
			oneLine(domain.DisplayName),
		)
		for _, action := range domain.Actions {
			fmt.Fprintf(&builder, "  %s — %s\n", action.Name, oneLine(action.Summary))
		}
		fmt.Fprintf(
			&builder,
			"\nRun `agentteam exec %s <action> --help` for details.\n",
			extensionName,
		)
		return builder.String(), true
	}
	return "", false
}

// RenderActionHelp returns usage and safety details for one authorized Action.
func (snapshot ExtensionSnapshot) RenderActionHelp(
	extensionName string,
	name string,
) (string, bool) {
	action, ok := snapshot.Action(extensionName, name)
	if !ok {
		return "", false
	}
	var builder strings.Builder
	fmt.Fprintf(
		&builder,
		"%s %s — %s\n",
		extensionName,
		name,
		oneLine(action.Summary),
	)
	fmt.Fprintf(
		&builder,
		"Usage: agentteam exec %s %s <json|->\n",
		extensionName,
		name,
	)
	if description := strings.TrimSpace(action.Description); description != "" {
		fmt.Fprintf(&builder, "Description: %s\n", description)
	}
	fmt.Fprintf(
		&builder,
		"Safety: class=%s\n",
		action.Safety.Class,
	)
	if action.Example != nil {
		if example, err := json.Marshal(action.Example); err == nil {
			fmt.Fprintf(&builder, "Example: %s\n", compactJSON(example))
		}
	}
	builder.WriteString("Schemas: --input-schema | --output-schema\n")
	return builder.String(), true
}

// RenderActionInputSchemaJSON returns one standalone authorized input schema.
func (snapshot ExtensionSnapshot) RenderActionInputSchemaJSON(
	extensionName string,
	name string,
) (string, bool) {
	action, ok := snapshot.Action(extensionName, name)
	if !ok {
		return "", false
	}
	return renderExtensionSchemaJSON(action.InputSchema)
}

// RenderActionOutputSchemaJSON returns one standalone authorized output schema.
func (snapshot ExtensionSnapshot) RenderActionOutputSchemaJSON(
	extensionName string,
	name string,
) (string, bool) {
	action, ok := snapshot.Action(extensionName, name)
	if !ok {
		return "", false
	}
	return renderExtensionSchemaJSON(action.OutputSchema)
}

// ExtensionPromptAction is one verified server-authorized action fact used by
// the compiler-owned Extension guidance template.
type ExtensionPromptAction struct {
	ExtensionName string
	ActionName    string
}

// PromptGuidanceActions returns the deterministic, typed action projection for
// the verified Extension Catalog. It does not render AgentTeam-owned prose.
func (snapshot ExtensionSnapshot) PromptGuidanceActions() []ExtensionPromptAction {
	if snapshot.Empty() {
		return nil
	}
	var actions []ExtensionPromptAction
	for _, domain := range snapshot.Domains() {
		for _, action := range domain.Actions {
			actions = append(actions, ExtensionPromptAction{ExtensionName: domain.ExtensionName, ActionName: action.Name})
		}
	}
	return actions
}

// RuntimeGuidance returns the persistent, secret-free discovery contract for
// one non-empty process Catalog. It is retained for API compatibility;
// runtime prompt compilation uses PromptGuidanceActions.
func (snapshot ExtensionSnapshot) RuntimeGuidance() string {
	if snapshot.Empty() {
		return ""
	}
	var builder strings.Builder
	builder.WriteString("This managed process has a private AgentTeam Extension Catalog.\n")
	builder.WriteString(
		"Only the Extension-name/Action pairs listed below are authorized for this process:\n",
	)
	for _, action := range snapshot.PromptGuidanceActions() {
		fmt.Fprintf(&builder, "- %s %s\n", action.ExtensionName, action.ActionName)
	}
	builder.WriteString(
		"Discover details with `agentteam exec --help`, " +
			"`agentteam exec <extension-name> --help`, or " +
			"`agentteam exec <extension-name> <action> --help`.\n",
	)
	builder.WriteString(
		"Inspect contracts with `agentteam exec <extension-name> <action> " +
			"--input-schema` or `--output-schema`; invoke with exactly one JSON value.\n",
	)
	return builder.String()
}

func renderExtensionSchemaJSON(schema map[string]any) (string, bool) {
	if schema == nil {
		schema = map[string]any{}
	}
	raw, err := json.MarshalIndent(schema, "", "  ")
	if err != nil {
		return "", false
	}
	return string(raw) + "\n", true
}
