// Copyright IBM Corp. 2015, 2025
// SPDX-License-Identifier: BUSL-1.1

package command

import (
	"fmt"
	"strings"

	"github.com/hashicorp/nomad/helper/winsvc"
	"github.com/posener/complete"
)

type WindowsServiceUninstallCommand struct {
	Meta
	serviceManagerFn  func() (winsvc.WindowsServiceManager, error)
	privilegedCheckFn func() bool
}

func (c *WindowsServiceUninstallCommand) AutoCompleteFlags() complete.Flags {
	return c.Meta.AutocompleteFlags(FlagSetDefault)
}

func (c *WindowsServiceUninstallCommand) Synopsis() string {
	return "Uninstall the nomad Windows system service"
}

func (c *WindowsServiceUninstallCommand) Name() string { return "windows service uninstall" }

func (c *WindowsServiceUninstallCommand) Help() string {
	helpText := `
Usage: nomad windows service uninstall [options]

  This command uninstalls nomad as a Windows system service.

General Options:

` + generalOptionsUsage(usageOptsDefault)
	return strings.TrimSpace(helpText)
}

func (c *WindowsServiceUninstallCommand) Run(args []string) int {
	flags := c.Meta.FlagSet(c.Name(), FlagSetDefault)
	flags.Usage = func() { c.Ui.Output(c.Help()) }

	if err := flags.Parse(args); err != nil {
		return 1
	}

	if args = flags.Args(); len(args) > 0 {
		c.Ui.Error("This command takes no arguments")
		c.Ui.Error(commandErrorText(c))
		return 1
	}

	// Set helper functions to default if unset
	if c.serviceManagerFn == nil {
		c.serviceManagerFn = winsvc.NewWindowsServiceManager
	}
	if c.privilegedCheckFn == nil {
		c.privilegedCheckFn = winsvc.IsPrivilegedProcess
	}

	// Check that command is being run with elevated permissions
	if !c.privilegedCheckFn() {
		c.Ui.Error("Service uninstall must be run with Administator privileges")
		return 1
	}

	c.Ui.Output("Uninstalling nomad Windows service...")

	m, err := c.serviceManagerFn()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Could not connect to Windows service manager - %s", err))
		return 1
	}
	defer m.Close()

	if err := c.performUninstall(m); err != nil {
		c.Ui.Error(fmt.Sprintf("Service uninstall failed: %s", err))
		return 1
	}

	c.Ui.Info("Successfully uninstalled nomad Windows service")
	return 0
}

func (c *WindowsServiceUninstallCommand) performUninstall(m winsvc.WindowsServiceManager) error {
	// Check that the nomad service is currently registered
	exists, err := m.IsServiceRegistered(winsvc.WINDOWS_SERVICE_NAME)
	if err != nil {
		return fmt.Errorf("unable to check for existing service - %w", err)
	}

	if !exists {
		return nil
	}

	// Grab the service and ensure the service is stopped
	srvc, err := m.GetService(winsvc.WINDOWS_SERVICE_NAME)
	if err != nil {
		return fmt.Errorf("could not get existing service - %w", err)
	}
	defer srvc.Close()

	if err := srvc.Stop(); err != nil {
		return fmt.Errorf("unable to stop service - %w", err)
	}

	// Remove the service from the event log
	if err := srvc.DisableEventlog(); err != nil {
		return fmt.Errorf("could not remove eventlog configuration - %w", err)
	}

	// Finally, delete the service
	if err := srvc.Delete(); err != nil {
		return fmt.Errorf("could not delete service - %w", err)
	}

	return nil
}
