// SPDX-License-Identifier: 0BSD
// Copyright (c) 2024-2026 Sudo-Ivan / Quad4.io
package common

import (
	"encoding/binary"
	"net"
	"sync"
	"time"
)

// NetworkInterface defines the interface for all network communication methods
type NetworkInterface interface {
	// Core interface operations
	Start() error
	Stop() error
	Enable()
	Disable()
	Detach()

	// Network operations
	Send(data []byte, address string) error
	GetConn() net.Conn
	GetMTU() int
	GetName() string

	// Interface properties
	GetType() InterfaceType
	GetMode() InterfaceMode
	IsEnabled() bool
	IsOnline() bool
	IsDetached() bool
	GetBandwidthAvailable() bool

	// Packet handling
	ProcessIncoming([]byte)
	ProcessOutgoing([]byte) error
	SendPathRequest([]byte) error
	SendLinkPacket([]byte, []byte, time.Time) error
	SetPacketCallback(PacketCallback)
	GetPacketCallback() PacketCallback
}

// BaseInterface provides common implementation for network interfaces
type BaseInterface struct {
	Name     string
	Mode     InterfaceMode
	Type     InterfaceType
	Online   bool
	Enabled  bool
	Detached bool

	IN  bool
	OUT bool

	MTU     int
	Bitrate int64

	TxBytes uint64
	RxBytes uint64
	lastTx  time.Time

	Mutex          sync.RWMutex
	Owner          interface{}
	PacketCallback PacketCallback
}

// NewBaseInterface creates a new BaseInterface instance
func NewBaseInterface(name string, ifaceType InterfaceType, enabled bool) BaseInterface {
	return BaseInterface{
		Name:    name,
		Type:    ifaceType,
		Mode:    IF_MODE_FULL,
		Enabled: enabled,
		MTU:     DEFAULT_MTU,
		Bitrate: BITRATE_MINIMUM,
		lastTx:  time.Now(),
	}
}

// Default implementations for BaseInterface
func (i *BaseInterface) GetType() InterfaceType {
	return i.Type
}

func (i *BaseInterface) GetMode() InterfaceMode {
	return i.Mode
}

func (i *BaseInterface) GetMTU() int {
	return i.MTU
}

func (i *BaseInterface) GetName() string {
	return i.Name
}

func (i *BaseInterface) IsEnabled() bool {
	i.Mutex.RLock()
	defer i.Mutex.RUnlock()
	return i.Enabled && i.Online && !i.Detached
}

func (i *BaseInterface) IsOnline() bool {
	i.Mutex.RLock()
	defer i.Mutex.RUnlock()
	return i.Online
}

func (i *BaseInterface) IsDetached() bool {
	i.Mutex.RLock()
	defer i.Mutex.RUnlock()
	return i.Detached
}

func (i *BaseInterface) SetPacketCallback(callback PacketCallback) {
	i.Mutex.Lock()
	defer i.Mutex.Unlock()
	i.PacketCallback = callback
}

func (i *BaseInterface) GetPacketCallback() PacketCallback {
	i.Mutex.RLock()
	defer i.Mutex.RUnlock()
	return i.PacketCallback
}

func (i *BaseInterface) Detach() {
	i.Mutex.Lock()
	defer i.Mutex.Unlock()
	i.Detached = true
	i.Online = false
}

func (i *BaseInterface) Enable() {
	i.Mutex.Lock()
	defer i.Mutex.Unlock()
	i.Enabled = true
	i.Online = true
}

func (i *BaseInterface) Disable() {
	i.Mutex.Lock()
	defer i.Mutex.Unlock()
	i.Enabled = false
	i.Online = false
}

// Default implementations that should be overridden by specific interfaces
func (i *BaseInterface) Start() error {
	return nil
}

func (i *BaseInterface) Stop() error {
	return nil
}

func (i *BaseInterface) GetConn() net.Conn {
	return nil
}

func (i *BaseInterface) Send(data []byte, address string) error {
	return i.ProcessOutgoing(data)
}

func (i *BaseInterface) ProcessIncoming(data []byte) {
	if i.PacketCallback != nil {
		i.PacketCallback(data, i)
	}
}

func (i *BaseInterface) ProcessOutgoing(data []byte) error {
	return nil
}

func (i *BaseInterface) SendPathRequest(data []byte) error {
	return i.Send(data, "")
}

func (i *BaseInterface) SendLinkPacket(dest []byte, data []byte, timestamp time.Time) error {
	// Create link packet
	packet := make([]byte, 0, len(dest)+len(data)+9) // 1 byte type + dest + 8 byte timestamp
	packet = append(packet, 0x02)                    // Link packet type
	packet = append(packet, dest...)

	ts := make([]byte, 8)
	binary.BigEndian.PutUint64(ts, uint64(timestamp.Unix())) // #nosec G115
	packet = append(packet, ts...)

	packet = append(packet, data...)

	return i.Send(packet, "")
}

func (i *BaseInterface) GetBandwidthAvailable() bool {
	i.Mutex.RLock()
	defer i.Mutex.RUnlock()

	// If no transmission in last second, bandwidth is available
	if time.Since(i.lastTx) > time.Second {
		return true
	}

	// Calculate current bandwidth usage
	bytesPerSec := float64(i.TxBytes) / time.Since(i.lastTx).Seconds()
	currentUsage := bytesPerSec * 8 // Convert to bits/sec

	// Check if usage is below threshold (2% of total bitrate)
	maxUsage := float64(i.Bitrate) * 0.02 // 2% propagation rate
	return currentUsage < maxUsage
}
