package main

import (
	"fmt"
	"os"
	"path/filepath"
)

// Paths mirror the bash profiler's layout so both tools can share on-disk
// state. They are resolved relative to the executable's directory (overridable
// with AWG_PROFILER_DIR), the Go analogue of the script's SCRIPT_DIR.
var (
	scriptDir    string
	configFile   string
	dataDir      string
	clientDir    string
	registryFile string
	statsFile    string
	stateFile    string

	// Directory awg-quick reads interface configs from (AmneziaWG default).
	awgConfDir = "/etc/amnezia/amneziawg"
)

func resolveScriptDir() string {
	if d := os.Getenv("AWG_PROFILER_DIR"); d != "" {
		return d
	}
	exe, err := os.Executable()
	if err != nil {
		die("Cannot determine executable path: %v", err)
	}
	if resolved, err := filepath.EvalSymlinks(exe); err == nil {
		exe = resolved
	}
	return filepath.Dir(exe)
}

func initPaths() {
	scriptDir = resolveScriptDir()
	configFile = filepath.Join(scriptDir, "awg_config")
	dataDir = filepath.Join(scriptDir, "data")
	clientDir = filepath.Join(scriptDir, "awg_clients")
	registryFile = filepath.Join(dataDir, "awg_clients.json")
	statsFile = filepath.Join(dataDir, "awg_stats.json")
	stateFile = filepath.Join(scriptDir, "awg_state.json")
}

func usage() {
	fmt.Print(`AmneziaWG Profiler — server + client management tool (AmneziaWG variant)

Usage: awg_profiler <command> [options]

SERVER SETUP
  install-deps             Install AmneziaWG, jq, qrencode for this OS and
                           record a deps-installed flag (run this FIRST)
  init-server              Interactive server setup: verifies dependencies are
                           installed, then generates keys + obfuscation
                           parameters, writes config, enables IP forwarding and
                           starts the service (does NOT install packages)

SERVER MANAGEMENT
  server-status            Show interface stats and peer list
  server-start             Start AmneziaWG service
  server-stop              Stop AmneziaWG service
  server-restart           Restart AmneziaWG service
  show-config              Print current config (private keys hidden)
  sync-config              Rebuild <conf-dir>/<iface>.conf from client
                           registry and optionally restart the service

CLIENT MANAGEMENT
  create  <name>           Create new VPN client; generates keys, .conf and QR
                           code
  delete  <id>             Remove client by ID (deletes files + registry entry)
  disable <id>             Set client status to DISABLED
  enable  <id>             Set client status to ACTIVE
  list                     List all registered clients

WEB UI
  web [--addr host:port]   Start the management web UI (default 127.0.0.1:8080).
                           Set AWG_WEB_USER + AWG_WEB_PASS for HTTP Basic auth.
      [--theme name]       Select the design (or AWG_WEB_THEME env):
                             classic  original Modern Dark UI (default)
                             glass    glassmorphism · Slate + Amber
      [--ui-mode mode]     Colour mode (or AWG_WEB_MODE env):
                             dark   force dark palette (default)
                             light  force light palette (classic only)
                             auto   follow the viewer's OS preference

Supported OS: Ubuntu, Debian, Linux Mint, Alpine Linux
`)
}

func main() {
	initPaths()

	args := os.Args[1:]
	cmd := ""
	if len(args) > 0 {
		cmd = args[0]
	}
	rest := args
	if len(args) > 0 {
		rest = args[1:]
	}

	switch cmd {

	case "init-server":
		initServer()

	case "install-deps":
		installDeps()

	case "server-status":
		requireBinary("awg")
		c := loadConfig()
		osInfo := detectOS()
		serverStatus(c, osInfo)

	case "server-start":
		c := loadConfig()
		osInfo := detectOS()
		serviceStart(osInfo, c.Interface)
		info("AmneziaWG started: %s", c.Interface)

	case "server-stop":
		c := loadConfig()
		osInfo := detectOS()
		serviceStop(osInfo, c.Interface)
		info("AmneziaWG stopped: %s", c.Interface)

	case "server-restart":
		c := loadConfig()
		osInfo := detectOS()
		serviceRestart(osInfo, c.Interface)
		info("AmneziaWG restarted: %s", c.Interface)

	case "show-config":
		showConfig()

	case "sync-config":
		// jq is no longer needed: the Go port reads/writes the registry natively.
		c := loadConfig()
		osInfo := detectOS()
		syncConfig(c, osInfo)

	case "create":
		requireBinary("awg")
		requireBinary("qrencode")
		c := loadConfig()
		initStorage()
		createClient(c, detectOS(), rest)

	case "delete":
		c := loadConfig()
		initStorage()
		deleteClient(c, detectOS(), rest)

	case "disable":
		c := loadConfig()
		initStorage()
		disableClient(c, detectOS(), rest)

	case "enable":
		c := loadConfig()
		initStorage()
		enableClient(c, detectOS(), rest)

	case "list":
		// load_config enforces that the server has been initialised first.
		loadConfig()
		initStorage()
		listClients()

	case "web":
		runWeb(rest)

	case "--help", "-h", "help", "":
		usage()

	default:
		fmt.Fprintf(os.Stderr, "Unknown command: %s\n\n", cmd)
		usage()
		os.Exit(1)
	}
}
