package bridge

import (
	"log"
	"time"

	"github.com/wormhole/wormhole/internal/protocol"
)

func (b *Bridge) startWatchdog() {
	go func() {
		ticker := time.NewTicker(WatchdogInterval)
		defer ticker.Stop()
		for range ticker.C {
			b.runWatchdog()
		}
	}()
}

func (b *Bridge) runWatchdog() {
	now := time.Now()
	b.mu.RLock()
	sessions := make([]*AgentSession, 0, len(b.agents))
	for _, agent := range b.agents {
		sessions = append(sessions, agent)
	}
	b.mu.RUnlock()

	for _, agent := range sessions {
		if agent.closed.Load() {
			continue
		}
		lastPing, ok := b.cache.AgentLastPing(agent.ClientID)
		if !ok {
			continue
		}
		since := now.Sub(lastPing)
		if since > HeartbeatTimeout {
			log.Printf("[bridge] client %d heartbeat timeout (%v), closing", agent.ClientID, since.Round(time.Second))
			agent.Close()
			continue
		}
		if since > ServerProbeAfter {
			go b.probeAgent(agent)
		}
	}
}

func (b *Bridge) probeAgent(agent *AgentSession) {
	if agent.closed.Load() {
		return
	}
	stream, err := agent.smux.OpenStream()
	if err != nil {
		return
	}
	defer stream.Close()

	if err := protocol.WriteMessage(stream, protocol.MsgPing, nil); err != nil {
		return
	}
	msgType, _, err := protocol.ReadMessage(stream)
	if err != nil || msgType != protocol.MsgPong {
		return
	}
	b.cache.TouchAgent(agent.ClientID)
}
