// Package capdiag collects read-only capability diagnostics for Skills,
// Commands, Hooks, plugin packages, MCP servers, and instruction docs.
// CLI and desktop share Collect; only CLI --live starts MCP processes.
package capdiag

import (
	"time"

	"reasonix/internal/plugin"
)

// SchemaVersion is the JSON report version. Bump only on breaking shape changes.
const SchemaVersion = 1

// Options configure Collect.
type Options struct {
	// Root is the workspace root (default: current working directory).
	Root string
	// Live starts automatic MCP servers in an isolated Host (CLI only).
	Live bool
	// LiveTimeout is the per-server probe timeout when Live is true.
	LiveTimeout time.Duration
	// RuntimeHost, when set, merges connected/failed/deferred status from an
	// existing Host (desktop active session). Collect never starts MCP when
	// RuntimeHost is set unless Live is also true (desktop passes Live=false).
	RuntimeHost *plugin.Host
	// HomeDir and ReasonixHomeDir override discovery roots (tests).
	HomeDir         string
	ReasonixHomeDir string
}

// Report is the stable capability diagnostics payload.
type Report struct {
	SchemaVersion int                 `json:"schema_version"`
	Root          string              `json:"root"`
	Live          bool                `json:"live"`
	Summary       Summary             `json:"summary"`
	Instructions  InstructionsReport  `json:"instructions"`
	Skills        AssetReport         `json:"skills"`
	Commands      AssetReport         `json:"commands"`
	Hooks         HookReport          `json:"hooks"`
	Plugins       PluginPackageReport `json:"plugins"`
	MCP           MCPReport           `json:"mcp"`
	Issues        []Issue             `json:"issues"`
}

// Summary counts issues and resources.
type Summary struct {
	Errors   int `json:"errors"`
	Warnings int `json:"warnings"`
	Infos    int `json:"infos"`

	Instructions int `json:"instructions"`
	Skills       int `json:"skills"`
	Commands     int `json:"commands"`
	Hooks        int `json:"hooks"`
	Plugins      int `json:"plugins"`
	MCPServers   int `json:"mcp_servers"`
}

// Issue is one diagnostic finding with a stable code.
type Issue struct {
	Severity    string `json:"severity"` // error | warning | info
	Code        string `json:"code"`
	Subsystem   string `json:"subsystem"`
	Name        string `json:"name,omitempty"`
	Source      string `json:"source,omitempty"`
	Message     string `json:"message"`
	Remediation string `json:"remediation,omitempty"`
	SettingsTab string `json:"settings_tab,omitempty"`
}

// InstructionsReport lists loaded instruction/memory docs in load order.
type InstructionsReport struct {
	Docs []InstructionDoc `json:"docs"`
}

// InstructionDoc is one REASONIX.md / AGENTS.md / CLAUDE.md source.
type InstructionDoc struct {
	Path      string `json:"path"`
	Scope     string `json:"scope"`
	Directory string `json:"directory,omitempty"`
	Depth     int    `json:"depth"`
	Order     int    `json:"order"`
}

// AssetReport covers skills or commands.
type AssetReport struct {
	Roots       []RootInfo   `json:"roots"`
	Entries     []AssetEntry `json:"entries"`
	Winners     int          `json:"winners"`
	Shadowed    int          `json:"shadowed"`
	Disabled    int          `json:"disabled,omitempty"`
	ParseErrors int          `json:"parse_errors,omitempty"`
}

// RootInfo is one discovery directory.
type RootInfo struct {
	Path   string `json:"path"`
	Scope  string `json:"scope,omitempty"`
	Status string `json:"status"`
}

// AssetEntry is one skill or command candidate.
type AssetEntry struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Scope       string `json:"scope,omitempty"`
	Path        string `json:"path"`
	Status      string `json:"status"` // winner | shadowed | disabled | error
	WinnerPath  string `json:"winner_path,omitempty"`
	Error       string `json:"error,omitempty"`
	RunAs       string `json:"run_as,omitempty"`
}

// HookReport covers hook configuration.
type HookReport struct {
	// TrustedProject is retained in schema v1 for compatibility. Project hooks
	// are enabled by default, so this is true whenever a project root is present.
	TrustedProject bool         `json:"trusted_project"`
	ProjectDefines bool         `json:"project_defines_hooks"`
	Sources        []HookSource `json:"sources"`
	Entries        []HookEntry  `json:"entries"`
}

// HookSource is one settings/manifest source.
type HookSource struct {
	Scope      string `json:"scope"`
	Path       string `json:"path"`
	Status     string `json:"status"`
	HookCount  int    `json:"hook_count"`
	ParseError string `json:"parse_error,omitempty"`
}

// HookEntry is one configured hook.
type HookEntry struct {
	Event       string `json:"event"`
	Match       string `json:"match,omitempty"`
	Command     string `json:"command,omitempty"`
	ContextFile string `json:"context_file,omitempty"`
	Description string `json:"description,omitempty"`
	TimeoutMS   int    `json:"timeout_ms,omitempty"`
	Scope       string `json:"scope"`
	Source      string `json:"source"`
	Blocking    bool   `json:"blocking"`
}

// PluginPackageReport covers installed plugin packages.
type PluginPackageReport struct {
	StatePath string              `json:"state_path,omitempty"`
	Packages  []PluginPackageInfo `json:"packages"`
}

// PluginPackageInfo is one installed package.
type PluginPackageInfo struct {
	Name         string `json:"name"`
	Enabled      bool   `json:"enabled"`
	Version      string `json:"version,omitempty"`
	Root         string `json:"root"`
	ManifestKind string `json:"manifest_kind,omitempty"`
	Skills       int    `json:"skills"`
	Commands     int    `json:"commands"`
	Hooks        int    `json:"hooks"`
	MCPServers   int    `json:"mcp_servers"`
	// Prompts, Themes, and Runtime are native Manifest v2 fields. They stay
	// omitempty so older diagnostic consumers see no shape change for legacy
	// packages.
	Prompts  int      `json:"prompts,omitempty"`
	Themes   int      `json:"themes,omitempty"`
	Runtime  bool     `json:"runtime,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
	Status   string   `json:"status"` // ok | missing_root | invalid_manifest | disabled
}

// MCPReport covers merged MCP server configuration and optional live/runtime state.
type MCPReport struct {
	Servers []MCPServerInfo `json:"servers"`
}

// MCPServerInfo is one merged MCP server.
type MCPServerInfo struct {
	Name             string        `json:"name"`
	Source           string        `json:"source,omitempty"` // user_config | project_config | project_mcp_json | plugin_package | host_session
	SourcePath       string        `json:"source_path,omitempty"`
	Effective        bool          `json:"effective"`
	PackageOwner     string        `json:"package_owner,omitempty"`
	Transport        string        `json:"transport"`
	StartIntent      string        `json:"start_intent"`      // automatic | off
	Command          string        `json:"command,omitempty"` // redacted path form
	URLHost          string        `json:"url_host,omitempty"`
	EnvKeys          []string      `json:"env_keys,omitempty"`
	HeaderKeys       []string      `json:"header_keys,omitempty"`
	RuntimeStatus    string        `json:"runtime_status,omitempty"` // connected | failed | deferred | disabled | skipped | probed
	ToolCount        int           `json:"tool_count,omitempty"`
	Tools            []MCPToolInfo `json:"tools,omitempty"`
	Error            string        `json:"error,omitempty"`
	StartupStage     string        `json:"startup_stage,omitempty"`
	StartupElapsedMS int64         `json:"startup_elapsed_ms,omitempty"`
	Stderr           string        `json:"stderr,omitempty"`
}

// MCPToolInfo is one tool discovered during live/runtime probe.
type MCPToolInfo struct {
	Name            string `json:"name"`
	ReadOnlyHint    bool   `json:"read_only_hint,omitempty"`
	DestructiveHint bool   `json:"destructive_hint,omitempty"`
}
