//go:build !android && !ios && !freebsd && !js

package main

import (
	"context"
	"os"
	"path/filepath"

	log "github.com/sirupsen/logrus"

	"github.com/netbirdio/netbird/client/internal/profilemanager"
	"github.com/netbirdio/netbird/client/mdm"
	"github.com/netbirdio/netbird/client/ui/preferences"
	"github.com/netbirdio/netbird/client/ui/services"
)

// autostartDefaultState carries the guard inputs of the one-time autostart
// default decision so the decision itself stays a pure, testable function.
type autostartDefaultState struct {
	supported    bool
	mdmDisabled  bool
	priorInstall bool
}

// shouldEnableAutostartDefault applies the first-run guards in order and
// returns whether autostart may be enabled, plus the reason when it may not.
func shouldEnableAutostartDefault(s autostartDefaultState) (bool, string) {
	switch {
	case !s.supported:
		return false, "autostart not supported on this platform"
	case s.mdmDisabled:
		return false, "autostart disabled by MDM policy"
	case s.priorInstall:
		return false, "existing NetBird installation"
	}
	return true, ""
}

// autostartDisabledByMDM reports whether the MDM policy manages the
// disableAutostart key in a way that must suppress the default. An
// unparseable managed value is treated as disabled to stay on the safe side.
func autostartDisabledByMDM(policy *mdm.Policy) bool {
	if !policy.HasKey(mdm.KeyDisableAutostart) {
		return false
	}
	disabled, ok := policy.GetBool(mdm.KeyDisableAutostart)
	return !ok || disabled
}

// netbirdFootprintExists reports whether the machine already carries NetBird
// daemon config or state, meaning this is not a genuinely fresh install. It is
// the update-safety gate for the autostart default: upgrading users always
// have a footprint, so an update can never trigger a autostart entry write.
func netbirdFootprintExists() bool {
	candidates := []string{
		profilemanager.DefaultConfigPath,
		filepath.Join(profilemanager.DefaultConfigPathDir, "config.json"),
		filepath.Join(profilemanager.DefaultConfigPathDir, "state.json"),
	}
	for _, path := range candidates {
		if path != "" && fileExists(path) {
			return true
		}
	}
	return false
}

// applyAutostartDefault runs the one-time launch-on-login default for genuinely
// fresh installs. The autostartInitialized marker is persisted before any
// enable attempt so a crash mid-flow degrades to "never enabled" instead of
// retrying autostart entry writes on every launch. A user's later disable in
// Settings is never overridden: the marker guarantees at-most-once, ever.
func applyAutostartDefault(ctx context.Context, autostart *services.Autostart, prefs *preferences.Store, prefsFileExisted bool) {
	mdmDisabled := autostartDisabledByMDM(mdm.LoadPolicy())

	if mdmDisabled {
		if enabled, err := autostart.IsEnabled(ctx); err != nil {
			log.Warnf("MDM disableAutostart: read autostart state: %v", err)
		} else if enabled {
			if err := autostart.SetEnabled(ctx, false); err != nil {
				log.Warnf("MDM disableAutostart: force off failed: %v", err)
			} else {
				log.Info("MDM disableAutostart enforced: autostart turned off")
			}
		}
	}

	priorFootprint := netbirdFootprintExists() || prefsFileExisted

	if prefs.Get().AutostartInitialized {
		return
	}
	if err := prefs.SetAutostartInitialized(true); err != nil {
		log.Warnf("persist autostart marker, skipping autostart default: %v", err)
		return
	}

	state := autostartDefaultState{
		supported:    autostart.Supported(ctx),
		mdmDisabled:  mdmDisabled,
		priorInstall: priorFootprint,
	}
	enable, reason := shouldEnableAutostartDefault(state)
	if !enable {
		log.Debugf("skipping autostart default: %s", reason)
		return
	}

	if err := autostart.SetEnabled(ctx, true); err != nil {
		log.Warnf("enable autostart on fresh install: %v", err)
		return
	}
	log.Info("autostart enabled by default on fresh install")
}

// fileExists reports whether path exists.
func fileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}
