package backend

import (
	"context"
	"dhcp/internal/dao"
	"dhcp/internal/dhcpServer/data"
	"dhcp/internal/dhcpServer/handler"
	"dhcp/model"
	"errors"
	"net"
	"net/netip"
)

var errParseSubnet = errors.New("failed to parse subnet mask")

type Backend struct{}

func NewBackend() handler.BackendReader {
	return &Backend{}
}

func (b *Backend) GetByMac(ctx context.Context, addr net.HardwareAddr, s string) (*data.DHCP, error) {
	dp, err := dao.GetDHCPByMac(addr.String())
	if err != nil {
		return nil, err
	}
	dhcp, err := translate(dp)
	if err != nil {
		return nil, err
	}
	return dhcp, nil
}

func (b *Backend) GetByIP(ctx context.Context, ip net.IP, s string) (*data.DHCP, error) {
	return nil, nil
}

func translate(dp model.DHCP) (*data.DHCP, error) {
	var d data.DHCP
	if dp.MACAddress != "" {
		d.MACAddress = net.HardwareAddr(dp.MACAddress)
	}
	if dp.IPAddress != "" {
		ip, err := netip.ParseAddr(dp.IPAddress)
		if err != nil {
			return nil, err
		}
		d.IPAddress = ip
	}
	if len(dp.DomainSearch) > 0 {
		d.DomainSearch = dp.DomainSearch
	}
	if dp.SubnetMask != "" {
		sm := net.ParseIP(dp.SubnetMask)
		if sm == nil {
			return nil, errParseSubnet
		}
		d.SubnetMask = net.IPMask(sm.To4())
	}
	if dp.DefaultGateway != "" {
		dg, err := netip.ParseAddr(dp.DefaultGateway)
		if err != nil {
			return nil, err
		}
		d.DefaultGateway = dg
	}
	if len(dp.NameServers) > 0 {
		for _, s := range dp.NameServers {
			ip := net.ParseIP(string(s))
			if ip == nil {
				break
			}
			d.NameServers = append(d.NameServers, ip)
		}
	}
	if dp.DomainName != "" {
		d.DomainName = dp.DomainName
	}
	if dp.BroadcastAddress != "" {
		ba, err := netip.ParseAddr(dp.BroadcastAddress)
		if err != nil {
			return nil, err
		}
		d.BroadcastAddress = ba
	}

	if len(dp.NTPServers) > 0 {
		for _, s := range dp.NTPServers {
			ip := net.ParseIP(string(s))
			if ip == nil {
				break
			}
			d.NTPServers = append(d.NTPServers, ip)
		}
	}
	if dp.VLANID != "" {
		d.VLANID = dp.VLANID
	}
	d.LeaseTime = uint32(dp.LeaseTime)
	if dp.DomainSearch != nil {
		d.DomainSearch = dp.DomainSearch
	}

	if dp.ServerIP != "" {
		d.ServerIP = net.ParseIP(dp.ServerIP)
	}
	return &d, nil
}
