// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause

// Package featureknob provides a facility to control whether features
// can run based on either an envknob or running OS / distro.
package featureknob

import (
	"errors"
	"runtime"

	"github.com/sagernet/tailscale/envknob"
	"github.com/sagernet/tailscale/hostinfo"
	"github.com/sagernet/tailscale/version"
	"github.com/sagernet/tailscale/version/distro"
)

// CanRunTailscaleSSH reports whether serving a Tailscale SSH server is
// supported for the current os/distro.
func CanRunTailscaleSSH() error {
	switch runtime.GOOS {
	case "linux":
		if distro.Get() == distro.Synology && !envknob.UseWIPCode() {
			return errors.New("The Tailscale SSH server does not run on Synology.")
		}
		if distro.Get() == distro.QNAP && !envknob.UseWIPCode() {
			return errors.New("The Tailscale SSH server does not run on QNAP.")
		}

		// Setting SSH on Home Assistant causes trouble on startup
		// (since the flag is not being passed to `tailscale up`).
		// Although Tailscale SSH does work here,
		// it's not terribly useful since it's running in a separate container.
		if hostinfo.GetEnvType() == hostinfo.HomeAssistantAddOn {
			return errors.New("The Tailscale SSH server does not run on HomeAssistant.")
		}
		// otherwise okay
	case "darwin":
		// okay only in tailscaled mode for now.
		if version.IsSandboxedMacOS() {
			return errors.New("The Tailscale SSH server does not run in sandboxed Tailscale GUI builds.")
		}
	case "freebsd", "openbsd":
	default:
		return errors.New("The Tailscale SSH server is not supported on " + runtime.GOOS)
	}
	if !envknob.CanSSHD() {
		return errors.New("The Tailscale SSH server has been administratively disabled.")
	}
	return nil
}

// CanUseExitNode reports whether using an exit node is supported for the
// current os/distro.
func CanUseExitNode() error {
	switch dist := distro.Get(); dist {
	case distro.Synology, // see https://github.com/tailscale/tailscale/issues/1995
		distro.QNAP:
		return errors.New("Tailscale exit nodes cannot be used on " + string(dist))
	}

	if hostinfo.GetEnvType() == hostinfo.HomeAssistantAddOn {
		return errors.New("Tailscale exit nodes cannot be used on HomeAssistant.")
	}

	return nil
}
