package server

import (
	"os"
	"path/filepath"
	"runtime"
	"time"
)

const (
	DefaultListen                        = "127.0.0.1:8765"
	DefaultTimeoutSeconds                = 30.0
	DefaultMaxWaitTimeoutSeconds         = 600.0
	DefaultIdleFlushSeconds              = 0.5
	DefaultTerminalCols                  = 200
	DefaultTerminalRows                  = 50
	DefaultOutputLimitBytes              = 16 * 1024
	MaxOutputLimitBytes                  = 512 * 1024
	DefaultListLimit                     = 50
	MaxListLimit                         = 200
	DefaultTerminateGraceSeconds         = 10.0
	DefaultGCIntervalSeconds             = 60.0
	DefaultGCFinishedJobRetentionSeconds = 300.0
	DefaultPollInterval                  = 50 * time.Millisecond
	DefaultPipeMonitorInterval           = 1 * time.Second
	DefaultPipeReadyTimeout              = 10 * time.Second
	DefaultSQLiteBusyTimeoutMs           = 5000
	DefaultAuthTokenEnv                  = "SHELLCTL_AUTH_TOKEN"
	HealthStatus                         = "ok"
)

// Config holds runtime configuration for the shellctl server.
type Config struct {
	Listen                       string
	AuthToken                    string
	StateDir                     string
	RuntimeDir                   string
	GCInterval                   time.Duration
	GCFinishedJobRetention       time.Duration
	DefaultTimeout               time.Duration
	MaxWaitTimeout               time.Duration
	IdleFlushDuration            time.Duration
	DefaultCwd                   string
	DefaultTerminalCols          int
	DefaultTerminalRows          int
	DefaultListLimit             int
	MaxListLimit                 int
	DefaultOutputLimitBytes      int
	MaxOutputLimitBytes          int
	DefaultTerminateGraceSeconds float64
	PollInterval                 time.Duration
	PipeMonitorInterval          time.Duration
	PipeReadyTimeout             time.Duration
	SQLiteBusyTimeoutMs          int
	SanitizePtyCommand           []string
	RunnerExitCommand            []string
}

// DefaultConfig returns a Config with sensible defaults.
func DefaultConfig() *Config {
	homeDir, _ := os.UserHomeDir()
	stateDir := defaultStateDir()
	runtimeDir := filepath.Join(stateDir, "runtime")

	cfg := &Config{
		Listen:                       DefaultListen,
		StateDir:                     stateDir,
		RuntimeDir:                   runtimeDir,
		GCInterval:                   time.Duration(DefaultGCIntervalSeconds * float64(time.Second)),
		GCFinishedJobRetention:       time.Duration(DefaultGCFinishedJobRetentionSeconds * float64(time.Second)),
		DefaultTimeout:               time.Duration(DefaultTimeoutSeconds * float64(time.Second)),
		MaxWaitTimeout:               time.Duration(DefaultMaxWaitTimeoutSeconds * float64(time.Second)),
		IdleFlushDuration:            time.Duration(DefaultIdleFlushSeconds * float64(time.Second)),
		DefaultCwd:                   homeDir,
		DefaultTerminalCols:          DefaultTerminalCols,
		DefaultTerminalRows:          DefaultTerminalRows,
		DefaultListLimit:             DefaultListLimit,
		MaxListLimit:                 MaxListLimit,
		DefaultOutputLimitBytes:      DefaultOutputLimitBytes,
		MaxOutputLimitBytes:          MaxOutputLimitBytes,
		DefaultTerminateGraceSeconds: DefaultTerminateGraceSeconds,
		PollInterval:                 DefaultPollInterval,
		PipeMonitorInterval:          DefaultPipeMonitorInterval,
		PipeReadyTimeout:             DefaultPipeReadyTimeout,
		SQLiteBusyTimeoutMs:          DefaultSQLiteBusyTimeoutMs,
		SanitizePtyCommand:           []string{"shellctl-sanitize-pty"},
		RunnerExitCommand:            []string{"shellctl-runner-exit"},
	}

	// Auth token from environment if not set explicitly
	if cfg.AuthToken == "" {
		cfg.AuthToken = os.Getenv(DefaultAuthTokenEnv)
	}

	return cfg
}

// JobsDir returns the path to the jobs artifact directory.
func (c *Config) JobsDir() string {
	return filepath.Join(c.StateDir, "jobs")
}

// DBPath returns the path to the SQLite database.
func (c *Config) DBPath() string {
	return filepath.Join(c.StateDir, "shellctl.db")
}

// TmuxSocket returns the path to the dedicated tmux socket.
func (c *Config) TmuxSocket() string {
	return filepath.Join(c.RuntimeDir, "tmux.sock")
}

// RunnerPath returns the path to the installed runner script.
func (c *Config) RunnerPath() string {
	return filepath.Join(c.RuntimeDir, "bin", "shellctl-runner")
}

func defaultStateDir() string {
	if runtime.GOOS == "darwin" {
		home, _ := os.UserHomeDir()
		return filepath.Join(home, ".local", "share", "shellctl")
	}
	if xdg := os.Getenv("XDG_DATA_HOME"); xdg != "" {
		return filepath.Join(xdg, "shellctl")
	}
	home, _ := os.UserHomeDir()
	return filepath.Join(home, ".local", "share", "shellctl")
}
