package talos

import (
	"fmt"
	"log/slog"

	"github.com/budimanjojo/talhelper/v3/pkg/config"
	"github.com/budimanjojo/talhelper/v3/pkg/patcher"
	tconfig "github.com/siderolabs/talos/pkg/machinery/config"
)

// AddMultiDocs appends multi-documents machine configuration to the main machine configuration
// generated by upstream API. The documents are generated and applied as a strategic merge patch.
// It also returns an error, if any.
func AddMultiDocs(node *config.Node, mode string, corecfg []byte, vc *tconfig.VersionContract) ([]byte, error) {
	extradocs, err := genMultiDocs(node, mode, vc)
	if err != nil {
		return nil, err
	}

	// TODO: A better way is to append them as documents and use upstream API
	// But the problem is upstream Generate API is generating not just the core config
	// Resulting in error because of duplicates with the ones we created
	return patcher.YamlBytesPatcher(extradocs, corecfg)
}

func genMultiDocs(node *config.Node, mode string, vc *tconfig.VersionContract) ([]byte, error) {
	var result []byte

	if vc.MultidocNetworkConfigSupported() {
		slog.Debug(fmt.Sprintf("generating hostname config for %s", node.Hostname))
		hc, err := GenerateNetworkHostnameConfigBytes(node.Hostname, node.IgnoreHostname)
		if err != nil {
			return nil, err
		}

		result = append(result, hc...)
	}

	if node.IngressFirewall != nil {
		slog.Debug(fmt.Sprintf("generating machine firewall config for %s", node.Hostname))
		nc, err := GenerateNetworkConfigBytes(node.IngressFirewall)
		if err != nil {
			return nil, err
		}
		result = append(result, nc...)
	}

	if len(node.ExtensionServices) > 0 {
		slog.Debug(fmt.Sprintf("generating machine extension service config for %s", node.Hostname))
		ext, err := GenerateExtensionServicesConfigBytes(node.ExtensionServices)
		if err != nil {
			return nil, err
		}
		result = append(result, ext...)
	}

	if len(node.Volumes) > 0 {
		slog.Debug(fmt.Sprintf("generating volume config for %s", node.Hostname))
		vc, err := GenerateVolumeConfigBytes(node.Volumes, mode)
		if err != nil {
			return nil, err
		}
		result = append(result, vc...)
	}

	if len(node.UserVolumes) > 0 {
		slog.Debug(fmt.Sprintf("generating user volume config for %s", node.Hostname))
		uvc, err := GenerateUserVolumeConfigBytes(node.UserVolumes, mode)
		if err != nil {
			return nil, err
		}
		result = append(result, uvc...)
	}

	return result, nil
}
