package cli

import (
	"net"
	"os"
	"path/filepath"

	"github.com/spf13/cobra"

	"github.com/Control-D-Inc/ctrld"
)

// Uninstall implements the logic from cmdUninstall.Run
func (sc *ServiceCommand) Uninstall(cmd *cobra.Command, args []string) error {
	logger := mainLog.Load()
	logger.Debug().Msg("Service uninstall command started")

	readConfig(false)
	v.Unmarshal(&cfg)

	s, p, err := sc.initializeServiceManager()
	if err != nil {
		logger.Error().Err(err).Msg("Failed to initialize service manager")
		return err
	}

	p.cfg = &cfg
	if iface == "" {
		iface = autoIface
	}
	p.preRun()
	if ir := runningIface(s); ir != nil {
		p.runningIface = ir.Name
		p.requiredMultiNICsConfig = ir.All
	}

	if err := checkDeactivationPin(s, nil); isCheckDeactivationPinErr(err) {
		logger.Error().Msg("Deactivation pin check failed")
		os.Exit(deactivationPinInvalidExitCode)
	}

	logger.Debug().Msg("Starting service uninstall")
	uninstall(p, s)

	if cleanup {
		logger.Debug().Msg("Performing cleanup operations")
		var files []string
		// Config file.
		files = append(files, v.ConfigFileUsed())
		// Log file and backup log file.
		// For safety, only process if log file path is absolute.
		if logFile := normalizeLogFilePath(cfg.Service.LogPath); filepath.IsAbs(logFile) {
			files = append(files, logFile)
			oldLogFile := logFile + oldLogSuffix
			if _, err := os.Stat(oldLogFile); err == nil {
				files = append(files, oldLogFile)
			}
		}
		// Socket files.
		if dir, _ := socketDir(); dir != "" {
			files = append(files, filepath.Join(dir, ctrldControlUnixSock))
			files = append(files, filepath.Join(dir, ctrldLogUnixSock))
		}
		// Static DNS settings files.
		withEachPhysicalInterfaces("", "", func(i *net.Interface) error {
			file := ctrld.SavedStaticDnsSettingsFilePath(i)
			files = append(files, file)
			return nil
		})
		bin, err := os.Executable()
		if err != nil {
			logger.Warn().Err(err).Msg("Failed to get executable path")
		}
		if bin != "" && supportedSelfDelete {
			files = append(files, bin)
		}
		// Backup file after upgrading.
		oldBin := bin + oldBinSuffix
		if _, err := os.Stat(oldBin); err == nil {
			files = append(files, oldBin)
		}
		for _, file := range files {
			if file == "" {
				continue
			}
			if err := os.Remove(file); err == nil {
				logger.Notice().Str("file", file).Msg("File removed during cleanup")
			} else {
				logger.Debug().Err(err).Str("file", file).Msg("Failed to remove file during cleanup")
			}
		}
		// Self-delete the ctrld binary if supported
		if err := selfDeleteExe(); err != nil {
			logger.Warn().Err(err).Msg("Failed to delete ctrld binary")
		} else {
			if !supportedSelfDelete {
				logger.Debug().Msgf("File removed: %s", bin)
			}
		}

		logger.Debug().Msg("Cleanup operations completed")
	}

	logger.Debug().Msg("Service uninstall command completed")
	return nil
}
