package cli

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

	"github.com/coreos/go-systemd/v22/dbus"
)

const (
	nmConfDir           = "/etc/NetworkManager/conf.d"
	nmCtrldConfFilename = "99-ctrld.conf"
	nmCtrldConfContent  = `[main]
dns=none
systemd-resolved=false
`
	nmSystemdUnitName = "NetworkManager.service"
)

var networkManagerCtrldConfFile = filepath.Join(nmConfDir, nmCtrldConfFilename)

// hasNetworkManager reports whether NetworkManager executable found.
// hasNetworkManager checks if NetworkManager is available on the system
func hasNetworkManager() bool {
	exe, _ := exec.LookPath("NetworkManager")
	return exe != ""
}

func (p *prog) setupNetworkManager() error {
	if !hasNetworkManager() {
		return nil
	}
	if content, _ := os.ReadFile(nmCtrldConfContent); string(content) == nmCtrldConfContent {
		p.Debug().Msg("NetworkManager already setup, nothing to do")
		return nil
	}
	err := os.WriteFile(networkManagerCtrldConfFile, []byte(nmCtrldConfContent), os.FileMode(0644))
	if os.IsNotExist(err) {
		p.Debug().Msg("NetworkManager is not available")
		return nil
	}
	if err != nil {
		p.Debug().Err(err).Msg("Could not write NetworkManager ctrld config file")
		return err
	}

	p.reloadNetworkManager()
			p.Debug().Msg("Setup NetworkManager done")
	return nil
}

func (p *prog) restoreNetworkManager() error {
	if !hasNetworkManager() {
		return nil
	}
	err := os.Remove(networkManagerCtrldConfFile)
	if os.IsNotExist(err) {
		p.Debug().Msg("NetworkManager is not available")
		return nil
	}
	if err != nil {
		p.Debug().Err(err).Msg("Could not remove NetworkManager ctrld config file")
		return err
	}

	p.reloadNetworkManager()
			p.Debug().Msg("Restore NetworkManager done")
	return nil
}

func (p *prog) reloadNetworkManager() {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()
	conn, err := dbus.NewSystemConnectionContext(ctx)
	if err != nil {
		p.Error().Err(err).Msg("Could not create new system connection")
		return
	}
	defer conn.Close()

	waitCh := make(chan string)
	if _, err := conn.ReloadUnitContext(ctx, nmSystemdUnitName, "ignore-dependencies", waitCh); err != nil {
		p.Debug().Err(err).Msg("Could not reload NetworkManager")
		return
	}
	<-waitCh
}
