// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package peer

import (
	"context"
	"sync/atomic"
	"time"

	validators "github.com/luxfi/validators"
	"github.com/luxfi/validators/uptime"
	"github.com/luxfi/ids"
	"github.com/luxfi/log"
	"github.com/luxfi/math/set"
	"github.com/luxfi/node/message"
	"github.com/luxfi/node/network/throttling"
	"github.com/luxfi/node/network/tracker"
	"github.com/luxfi/node/version"
	"github.com/luxfi/timer/mockable"
)

// InboundHandler handles inbound messages
type InboundHandler interface {
	HandleInbound(ctx context.Context, msg message.InboundMessage)
}

// InboundHandlerFunc is a function adapter for InboundHandler
type InboundHandlerFunc func(context.Context, message.InboundMessage)

func (f InboundHandlerFunc) HandleInbound(ctx context.Context, msg message.InboundMessage) {
	f(ctx, msg)
}

type Config struct {
	// Size, in bytes, of the buffer this peer reads messages into
	ReadBufferSize int
	// Size, in bytes, of the buffer this peer writes messages into
	WriteBufferSize int
	Clock           mockable.Clock
	Metrics         *Metrics
	MessageCreator  message.Creator

	Log                  log.Logger
	InboundMsgThrottler  throttling.InboundMsgThrottler
	Network              Network
	Router               InboundHandler
	VersionCompatibility version.Compatibility
	MyNodeID             ids.NodeID
	// MyChains does not include the primary network ID
	MyChains           set.Set[ids.ID]
	Beacons            validators.Manager
	Validators         validators.Manager
	NetworkID          uint32
	PingFrequency      time.Duration
	PongTimeout        time.Duration
	MaxClockDifference time.Duration

	SupportedLPs []uint32
	ObjectedLPs  []uint32

	// Unix time of the last message sent and received respectively
	// Must only be accessed atomically
	LastSent, LastReceived int64

	// Tracks CPU/disk usage caused by each peer.
	ResourceTracker tracker.ResourceTracker

	// Calculates uptime of peers
	UptimeCalculator uptime.Calculator

	// Signs my IP so I can send my signed IP address in the Handshake message
	IPSigner *IPSigner

	// IngressConnectionCount counts the ingress (to us) connections.
	IngressConnectionCount atomic.Int64

	// PQHandshakeConfig pins the strict-PQ application-layer handshake
	// (ML-KEM session + ML-DSA-65 identity) the peer goroutine runs
	// after the TLS upgrade. Non-nil on strict-PQ chains; nil leaves the
	// peer on the legacy bare-TLS path. Shared across every peer
	// instance for the same chain — never mutated post-construction.
	PQHandshakeConfig *HandshakeConfig

	// PQLocalIdentity is this node's ML-DSA-65 long-term identity. The
	// per-session ML-KEM keypair is regenerated inside the handshake; the
	// identity is the only persistent secret. Non-nil iff
	// PQHandshakeConfig is non-nil.
	PQLocalIdentity *LocalIdentity
}
