package config

import (
	"fmt"
	"git.kuschku.de/justjanne/terraform-provider-mullvad/api"
	"net/netip"
)

type Result struct {
	Config string
	Peer   []string
}

func GenerateConfig(c *MullvadContext, serverHostname string, privateKey api.WireguardKey) (Result, error) {
	servers, err := c.Client.ListServers()
	if err != nil {
		return Result{}, fmt.Errorf("could not load server list: %w", err)
	}
	server, err := servers.Wireguard.FindServer(serverHostname)
	if err != nil {
		return Result{}, fmt.Errorf("could not find server: %w", err)
	}
	endpoints, err := c.Client.GetEndpoints(c.AccountId, privateKey.PublicKey())
	if err != nil {
		return Result{}, fmt.Errorf("could not get wireguard endpoints: %w", err)
	}
	port, err := findPort(servers.Wireguard.PortRanges)
	if err != nil {
		return Result{}, fmt.Errorf("could not find suitable port for wireguard endpoint: %w", err)
	}

	wireguardConfig, err := templateConfig(configData{
		InterfacePrivateKey: privateKey,
		InterfaceAddress:    endpoints,
		InterfaceGateways: []netip.Addr{
			servers.Wireguard.IPv4Gateway,
			servers.Wireguard.IPv6Gateway,
		},
		PeerPublicKey: server.PublicKey,
		PeerEndpoint:  netip.AddrPortFrom(server.IPv4Endpoint, port),
	})
	if err != nil {
		return Result{}, fmt.Errorf("could not generate wireguard config: %w", err)
	}

	return Result{
		Config: wireguardConfig,
		Peer: []string{
			server.IPv4Endpoint.String(),
		},
	}, nil
}

func findPort(portRanges [][]uint16) (uint16, error) {
	if portRanges == nil || len(portRanges) == 0 {
		return 0, fmt.Errorf("no port available")
	}
	for _, portRange := range portRanges {
		if len(portRange) == 2 {
			return portRange[0], nil
		}
	}
	return 0, fmt.Errorf("no port available")
}