package db

import (
	"errors"
	"net/netip"
	"strings"
)

var (
	ErrInvalidIP       = errors.New("invalid IP")
	ErrNonPrivateIP    = errors.New("non-private IP")
	ErrInvalidPort     = errors.New("invalid port")
	ErrInvalidNetName  = errors.New("invalid network name")
	ErrInvalidPeerName = errors.New("invalid peer name")
)

func Config_Sanitize(c *Config) {
}

func Config_Validate(c *Config) error {
	return nil
}

func Session_Sanitize(s *Session) {
}

func Session_Validate(s *Session) error {
	return nil
}

func Network_Sanitize(n *Network) {
	n.Name = strings.TrimSpace(n.Name)

	if addr, ok := netip.AddrFromSlice(n.Network); ok {
		n.Network = addr.AsSlice()
	}
}

func Network_Validate(c *Network) error {
	// 16 bytes is linux limit for network interface names.
	if len(c.Name) == 0 || len(c.Name) > 16 {
		return ErrInvalidNetName
	}

	for _, c := range c.Name {
		if c >= 'a' && c <= 'z' {
			continue
		}
		if c >= '0' && c <= '9' {
			continue
		}
		return ErrInvalidNetName
	}

	addr, ok := netip.AddrFromSlice(c.Network)
	if !ok || !addr.Is4() || addr.As4()[3] != 0 || addr.As4()[0] == 0 {
		return ErrInvalidIP
	}

	if !addr.IsPrivate() {
		return ErrNonPrivateIP
	}

	return nil
}

func Peer_Sanitize(p *Peer) {
	p.Name = strings.TrimSpace(p.Name)
	if len(p.PublicIP) != 0 {
		addr, ok := netip.AddrFromSlice(p.PublicIP)
		if ok && addr.Is4() {
			p.PublicIP = addr.AsSlice()
		}
	}
	if p.Port == 0 {
		p.Port = 456
	}
}

func Peer_Validate(p *Peer) error {
	if len(p.PublicIP) > 0 {
		_, ok := netip.AddrFromSlice(p.PublicIP)
		if !ok {
			return ErrInvalidIP
		}
	}
	if p.Port == 0 {
		return ErrInvalidPort
	}

	for _, c := range p.Name {
		if c >= 'a' && c <= 'z' {
			continue
		}
		if c >= '0' && c <= '9' {
			continue
		}
		if c == '.' || c == '-' || c == '_' {
			continue
		}

		return ErrInvalidPeerName
	}

	return nil
}
