package cmd

import (
	"fmt"
	"os"
	"runtime"
	"strings"
	"time"

	"github.com/spf13/cobra"

	"github.com/tidbcloud/AgentTeam/desktop/internal/version"
)

var docOpts struct {
	manPage   bool
	install   bool
	skillFile bool
}

var docCmd = &cobra.Command{
	Use:   "doc",
	Short: "Generate documentation",
	Long: `Generate documentation for agentteam in various formats.

Without any flags, prints the help documentation to stdout.

Flags:
  --man      Output a man page in roff format
  --install  Install the man page to the system man directory (requires --man)
  --skill    Output Agent skill format markdown (for AI coding agents)`,
	Example: `  agentteam doc                    Print help documentation
  agentteam doc --man              Generate man page to stdout
  agentteam doc --man --install    Install man page to system
  agentteam doc --skill            Generate agent skill markdown`,
	RunE: func(cmd *cobra.Command, args []string) error {
		manPage := docOpts.manPage || docOpts.install
		if manPage && docOpts.skillFile {
			return fmt.Errorf("--man and --skill are mutually exclusive")
		}

		switch {
		case docOpts.install:
			return installManPage()
		case docOpts.skillFile:
			return printSkillDoc()
		case manPage:
			return printManPage()
		default:
			return cmd.Help()
		}
	},
}

func init() {
	docCmd.Flags().BoolVar(&docOpts.manPage, "man", false, "output man page in roff format")
	docCmd.Flags().BoolVar(&docOpts.install, "install", false, "install man page to system man directory (requires --man)")
	docCmd.Flags().BoolVar(&docOpts.skillFile, "skill", false, "output agent skill markdown")
}

func generateManPage() string {
	ver := version.BuildVersion()
	date := time.Now().Format("2006-01-02")

	var b strings.Builder
	fmt.Fprintf(&b, `.TH "AGENTTEAM" "1" "%s" "agentteam %s" "User Commands"
.SH "NAME"
agentteam \- AgentTeam daemon and command-line client
.SH "SYNOPSIS"
.B agentteam
\fIcommand\fR [\fIflags\fR]
.SH "DESCRIPTION"
agentteam is the AgentTeam daemon and command-line client for this machine.
It connects this machine to AgentTeam, runs local agent runtimes, exposes the
authenticated local API, and manages local workspaces, apps, channels, and
the background daemon service.
.SH "COMMANDS"
.SS "onboard"
Interactive first\-time setup wizard.
.RS
Creates the default configuration directory and files, auto\-detects available
AI coding agent runtimes, optionally installs agentteam as a service, and runs
diagnostics to verify the installation.
Flags: \fB\-\-runtime\fR to skip the full wizard and directly enter the
runtime detection view.
.RE
.SS "daemon"
Start the AgentTeam daemon in the foreground.
.RS
The daemon connects this machine to AgentTeam, runs local agent runtimes, exposes the
authenticated local API, and manages local workspaces, apps, and channels.
Use \fB\-\-server\-url\fR and \fB\-\-api\-key\fR to save AgentTeam machine settings before startup.
Flags: \fB\-\-connect\fR, \fB\-\-server\-url\fR,
\fB\-\-api\-key\fR, \fB\-\-host\fR, \fB\-\-port\fR (runtime overrides),
.RE
.SS "channel"
Manage messaging channels.
.RS
Subcommands: \fBlist\fR, \fBget\fR, \fBadd\fR, \fBupdate\fR,
\fBdelete\fR, \fBenable\fR, \fBdisable\fR.
Each channel connects to a AgentTeam server and
routes messages to AI agents.
.RE
.SS "agent"
Inspect synced AI agents.
.RS
Subcommands: \fBlist\fR, \fBget\fR.
Agents are synced from remote AgentTeam servers; create, update, or remove agents
from the corresponding AgentTeam server.
.RE
.SS "doctor"
Run diagnostics to verify the agentteam installation.
.RS
Checks configuration, runtimes, and daemon status. Use \fB\-\-fix\-runtime\fR
to print runtime remediation guidance.
.RE
.SS "upgrade"
Check for updates and upgrade agentteam.
.RS
Use \fB\-\-check\fR to only check for available updates without installing.
Without \fB\-\-check\fR, the command starts a background upgrade helper.
.RE
.SS "service"
Manage the agentteam system service lifecycle.
.RS
Subcommands: \fBinstall\fR, \fBuninstall\fR, \fBreinstall\fR,
\fBstart\fR, \fBstop\fR, \fBrestart\fR.
On Linux, use \fB\-\-user\fR with these commands to target the current user's
systemd manager instead of the system manager. User services start with the
user's systemd manager; enable lingering if you need boot\-time startup before
login.
.RE
.SS "status"
Show agentteam service status.
.RS
On Linux, \fBagentteam status\fR checks both the system and user systemd managers.
Installed services are shown even when inactive or failed. Use \fB\-\-user\fR
to inspect only the current user's systemd service.
Flags: \fB\-\-format\fR/\fB\-f\fR (table, json, jsonc, yaml, toml).
.RE
.SS "journal" (alias: "j")
View agentteam service logs.
.RS
Flags: \fB\-\-tail N\fR, \fB\-\-head N\fR, \fB\-f\fR/\fB\-\-follow\fR.
.RE
.SS "OPTIONS"
\fB\-\-version\fR, \fB\-v\fR
    Print version and build information.
.RS
Use \fB\-\-format\fR/\fB\-f\fR to control output (table, json, jsonc, yaml, toml).
.RE
.SS "doc"
Generate documentation (this command).
.RS
Use \fB\-\-man\fR for roff man page, \fB\-\-man \-\-install\fR to install to
the system, \fB\-\-skill\fR for agent skill markdown.
.RE
.SH "OPTIONS"
\fB\-\-help\fR, \fB\-h\fR
    Show help for the root command or any subcommand.
.SH "EXAMPLES"
.EX
agentteam onboard                # First-time setup
agentteam onboard --runtime      # Runtime detection status
agentteam daemon                 # Start daemon in foreground
agentteam daemon --server-url https://agentteam.example.com --api-key <machineApiKey>
agentteam service install        # Install as system service
agentteam service install --user # Install as user-level systemd service on Linux
agentteam status                 # Check service status
agentteam status --user          # Check the user-level systemd service on Linux
agentteam journal --tail 50      # View last 50 log lines
agentteam j -f                   # Follow log output (alias)
agentteam channel list           # List all channels
agentteam agent list             # List synced agents
agentteam doctor                 # Run diagnostics
agentteam upgrade                # Upgrade to latest version
agentteam --version              # Print version information
agentteam --version -f json      # Print version as JSON
.EE
.SH "CONFIGURATION"
The configuration file is located at \fB$HOME/.agentteam/config.yaml\fR.
Override the profile directory with the \fBAGENTTEAM_CONFIG_DIR\fR environment variable.
Run \fBagentteam onboard\fR to create the initial configuration.
.SH "SEE ALSO"
Full documentation: \fIhttps://agentteam.pingcap.com/docs\fR
.SH "AUTHOR"
agentteam contributors
`, date, ver)
	return b.String()
}

func printManPage() error {
	fmt.Print(generateManPage())
	return nil
}

func installManPage() error {
	manDir := "/usr/local/share/man/man1"
	if runtime.GOOS == "linux" {
		if d := os.Getenv("MANPATH"); d != "" {
			dirs := strings.Split(d, ":")
			for _, dir := range dirs {
				if dir != "" {
					manDir = dir
					break
				}
			}
		}
	}

	targetDir := manDir
	if _, err := os.Stat(targetDir); os.IsNotExist(err) {
		if err := os.MkdirAll(targetDir, 0755); err != nil {
			return fmt.Errorf("failed to create man directory %s: %w", targetDir, err)
		}
	}

	target := targetDir + "/agentteam.1"
	content := generateManPage()
	if err := os.WriteFile(target, []byte(content), 0644); err != nil {
		return fmt.Errorf("failed to write man page to %s: %w", target, err)
	}

	fmt.Printf("man page installed to %s\n", target)
	fmt.Println("Run 'man agentteam' to view the manual.")
	return nil
}

func printSkillDoc() error {
	ver := version.BuildVersion()

	skill := fmt.Sprintf(`---
title: agentteam
 description: AgentTeam daemon, CLI, and local runtime manager
version: %s
---

# agentteam

AgentTeam daemon and command-line client for this machine. It connects this machine
to AgentTeam, runs local agent runtimes, exposes the authenticated local API, and
manages local workspaces, apps, channels, and the background daemon service.

## Commands

### `+"`"+`agentteam onboard`+"`"+`
Interactive first-time setup wizard. Creates configuration, detects runtimes,
optionally installs as system service, and runs diagnostics.
Flags: `+"`"+`--runtime`+"`"+` to skip the wizard and print runtime detection status.

### `+"`"+`agentteam daemon`+"`"+`
Start the AgentTeam daemon in the foreground. Electron owns the desktop application
shell on macOS and Windows.
Use `+"`"+`--server-url`+"`"+` and `+"`"+`--api-key`+"`"+` to save AgentTeam machine settings before startup.
Flags: `+"`"+`--connect`+"`"+`, `+"`"+`--server-url`+"`"+`, `+"`"+`--api-key`+"`"+`, `+"`"+`--host`+"`"+`, `+"`"+`--port`+"`"+` (runtime overrides).

### `+"`"+`agentteam channel`+"`"+`
Manage messaging channels. Each channel connects to a AgentTeam server and routes messages to AI agents.
- `+"`"+`agentteam channel list`+"`"+` — List all channels
- `+"`"+`agentteam channel add [name]`+"`"+` — Add a AgentTeam channel
- `+"`"+`agentteam channel get <id>`+"`"+` — Show channel details
- `+"`"+`agentteam channel update <id>`+"`"+` — Update a channel
- `+"`"+`agentteam channel delete <id>`+"`"+` — Delete a channel
- `+"`"+`agentteam channel enable <id>`+"`"+` — Enable a channel
- `+"`"+`agentteam channel disable <id>`+"`"+` — Disable a channel

### `+"`"+`agentteam agent`+"`"+`
Inspect AI agents synced from remote AgentTeam servers. Local CLI management is read-only; create, update, or remove agents from the corresponding AgentTeam server.
- `+"`"+`agentteam agent list`+"`"+` — List all agents
- `+"`"+`agentteam agent get <id>`+"`"+` — Show agent details

### `+"`"+`agentteam service`+"`"+`
Manage the system service lifecycle.
- `+"`"+`agentteam service install`+"`"+` — Install as platform-native service (launchd/systemd/Windows Service). Flags: `+"`"+`--user`+"`"+` (Linux systemd user service)
- `+"`"+`agentteam service uninstall`+"`"+` — Remove the system service
- `+"`"+`agentteam service reinstall`+"`"+` — Reinstall the system service (picks up config changes). Flags: `+"`"+`--user`+"`"+` (Linux systemd user service)
- `+"`"+`agentteam service start`+"`"+` — Start the service (Linux/Windows only; macOS uses launchd auto-start). Flag: `+"`"+`--user`+"`"+` on Linux for the current user's systemd manager
- `+"`"+`agentteam service stop`+"`"+` — Stop the service (Linux/Windows only). Flag: `+"`"+`--user`+"`"+` on Linux for the current user's systemd manager
- `+"`"+`agentteam service restart`+"`"+` — Restart the service
- Linux `+"`"+`--user`+"`"+` services start with the current user's systemd manager; enable lingering if you need them before login.

### `+"`"+`agentteam status`+"`"+`
Show service status.
- On Linux, `+"`"+`agentteam status`+"`"+` checks both the system and user systemd managers and shows installed services even when inactive or failed
- `+"`"+`agentteam status --user`+"`"+` — Show only the current user's systemd service on Linux
- Flags: `+"`"+`--format`+"`"+`/`+"`"+`-f`+"`"+` (table|json|jsonc|yaml|toml)

### `+"`"+`agentteam journal`+"`"+` (alias: `+"`"+`j`+"`"+`)
View service logs.
Flags: `+"`"+`--tail N`+"`"+`, `+"`"+`--head N`+"`"+`, `+"`"+`-f`+"`"+`/`+"`"+`--follow`+"`"+` (real-time).

### `+"`"+`agentteam doctor`+"`"+`
Run diagnostics to verify installation. Checks configuration, runtimes, and daemon status.
Flags: `+"`"+`--fix-runtime`+"`"+` to print runtime remediation guidance.

### `+"`"+`agentteam upgrade`+"`"+`
Check for updates and upgrade agentteam.
Flags: `+"`"+`--check`+"`"+` to only check without downloading. `+"`"+`--base-url`+"`"+` for custom release server.

### `+"`"+`agentteam --version`+"`"+`
Print version and build information.
Flags: `+"`"+`--format`+"`"+`/`+"`"+`-f`+"`"+` (table|json|jsonc|yaml|toml).

### `+"`"+`agentteam doc`+"`"+`
Generate documentation.
Flags: `+"`"+`--man`+"`"+` (roff man page), `+"`"+`--man --install`+"`"+` (install to system), `+"`"+`--skill`+"`"+` (agent skill markdown).

## Configuration

Configuration file: `+"`"+`$HOME/.agentteam/config.yaml`+"`"+`.
Override the profile directory with the `+"`"+`AGENTTEAM_CONFIG_DIR`+"`"+` environment variable.

## Common Output Format Flags

Many commands support `+"`"+`--format`+"`"+`/`+"`"+`-f`+"`"+` with values: `+"`"+`table`+"`"+`, `+"`"+`json`+"`"+`, `+"`"+`jsonc`+"`"+`, `+"`"+`yaml`+"`"+`, `+"`"+`toml`+"`"+`.
`, ver)

	fmt.Print(skill)
	return nil
}
