package debpack

import (
	"fmt"
	"path/filepath"
	"strings"

	"tailscale.com/util/miragebrand"
)

const (
	DefaultPackageName = "mirage-qt"
	DefaultSummary     = "Mirage Linux tray client"
)

type Layout struct {
	CLIPath      string
	DaemonPath   string
	LauncherPath string
	UIPath       string
	ServicePath  string
	DefaultsPath string
	DesktopPath  string
	AppIconPath  string
}

type ControlMetadata struct {
	Package      string
	Version      string
	Architecture string
	Depends      []string
	Recommends   []string
	Maintainer   string
}

func DefaultLayout() Layout {
	return Layout{
		CLIPath:      "/usr/bin/mirage",
		DaemonPath:   "/usr/bin/miraged",
		LauncherPath: "/usr/bin/mirage-qt",
		UIPath:       "/usr/lib/mirage/mirage-qt-ui",
		ServicePath:  "/lib/systemd/system/miraged.service",
		DefaultsPath: "/etc/default/miraged",
		DesktopPath:  "/usr/share/applications/mirage-qt-ui.desktop",
		AppIconPath:  "/usr/share/pixmaps/mirage.png",
	}
}

func ControlFile(meta ControlMetadata) string {
	maintainer := strings.TrimSpace(meta.Maintainer)
	if maintainer == "" {
		maintainer = "Mirage"
	}

	var b strings.Builder
	fmt.Fprintf(&b, "Package: %s\n", meta.Package)
	fmt.Fprintf(&b, "Version: %s\n", meta.Version)
	b.WriteString("Section: net\n")
	b.WriteString("Priority: optional\n")
	fmt.Fprintf(&b, "Architecture: %s\n", meta.Architecture)
	fmt.Fprintf(&b, "Maintainer: %s\n", maintainer)
	if len(meta.Depends) > 0 {
		fmt.Fprintf(&b, "Depends: %s\n", strings.Join(meta.Depends, ", "))
	}
	if len(meta.Recommends) > 0 {
		fmt.Fprintf(&b, "Recommends: %s\n", strings.Join(meta.Recommends, ", "))
	}
	fmt.Fprintf(&b, "Description: %s\n", DefaultSummary)
	b.WriteString(" Mirage Linux client bundle with CLI, daemon, and Qt tray shell.\n")
	b.WriteString(" Includes mirage, miraged, mirage-qt, mirage-qt-ui, and a\n")
	b.WriteString(" miraged systemd service unit for Linux desktop integration.\n")
	return b.String()
}

func PostinstScript() string {
	return `#!/bin/sh
set -e
if command -v systemctl >/dev/null 2>&1; then
  systemctl daemon-reload >/dev/null 2>&1 || true
  systemctl enable miraged.service >/dev/null 2>&1 || true
  systemctl restart miraged.service >/dev/null 2>&1 || systemctl start miraged.service >/dev/null 2>&1 || true
fi
if command -v update-desktop-database >/dev/null 2>&1; then
  update-desktop-database -q /usr/share/applications || true
fi
exit 0
`
}

func PostrmScript() string {
	return `#!/bin/sh
set -e
if command -v systemctl >/dev/null 2>&1; then
  systemctl daemon-reload >/dev/null 2>&1 || true
fi
if command -v update-desktop-database >/dev/null 2>&1; then
  update-desktop-database -q /usr/share/applications || true
fi
exit 0
`
}

func ServiceFile() string {
	runtimeDir := filepath.Base(filepath.Dir(miragebrand.LinuxSocketPath()))
	stateDir := filepath.Base(filepath.Dir(miragebrand.LinuxStateFile()))
	return `[Unit]
Description=Mirage node agent
Documentation=https://tailscale.com/kb/
Wants=network-pre.target
After=network-pre.target NetworkManager.service systemd-resolved.service

[Service]
EnvironmentFile=-/etc/default/miraged
ExecStart=/usr/bin/miraged --state=` + miragebrand.LinuxStateFile() + ` --socket=` + miragebrand.LinuxSocketPath() + ` --port=${PORT} $FLAGS
ExecStopPost=/usr/bin/miraged --cleanup

Restart=on-failure

RuntimeDirectory=` + runtimeDir + `
RuntimeDirectoryMode=0755
StateDirectory=` + stateDir + `
StateDirectoryMode=0700
CacheDirectory=` + stateDir + `
CacheDirectoryMode=0750
Type=notify

[Install]
WantedBy=multi-user.target
`
}

func DefaultsFile() string {
	return `# Set the port to listen on for incoming VPN packets.
# Remote nodes will automatically be informed about the new port number,
# but you might want to configure this in order to set external firewall
# settings.
PORT="41641"

# Extra flags you might want to pass to miraged.
FLAGS=""
`
}
