package internal

import (
	"context"
	"os/exec"
	"strings"
	"sync"
	"time"

	"github.com/netbirdio/netbird/client/internal/peer"
)

type SessionWatcher struct {
	ctx   context.Context
	mutex sync.Mutex

	peerStatusRecorder *peer.Status
	watchTicker        *time.Ticker

	sendNotification bool
	onExpireListener func()
}

// NewSessionWatcher creates a new instance of SessionWatcher.
func NewSessionWatcher(ctx context.Context, peerStatusRecorder *peer.Status) *SessionWatcher {
	s := &SessionWatcher{
		ctx:                ctx,
		peerStatusRecorder: peerStatusRecorder,
		watchTicker:        time.NewTicker(2 * time.Second),
	}
	go s.startWatcher()
	return s
}

// SetOnExpireListener sets the callback func to be called when the session expires.
func (s *SessionWatcher) SetOnExpireListener(onExpire func()) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	s.onExpireListener = onExpire
}

// startWatcher continuously checks if the session requires login and
// calls the onExpireListener if login is required.
func (s *SessionWatcher) startWatcher() {
	for {
		select {
		case <-s.ctx.Done():
			s.watchTicker.Stop()
			return
		case <-s.watchTicker.C:
			managementState := s.peerStatusRecorder.GetManagementState()
			if managementState.Connected {
				s.sendNotification = true
			}

			isLoginRequired := s.peerStatusRecorder.IsLoginRequired()
			if isLoginRequired && s.sendNotification && s.onExpireListener != nil {
				s.mutex.Lock()
				s.onExpireListener()
				s.sendNotification = false
				s.mutex.Unlock()
			}
		}
	}
}

// CheckUIApp checks whether UI application is running.
func CheckUIApp() bool {
	cmd := exec.Command("ps", "-ef")
	output, err := cmd.Output()
	if err != nil {
		return false
	}

	lines := strings.Split(string(output), "\n")
	for _, line := range lines {
		if strings.Contains(line, "netbird-ui") && !strings.Contains(line, "grep") {
			return true
		}
	}
	return false
}