package restic

import (
	"fmt"
	"io"
	"os"
	"strings"

	"git.secluded.site/keld/internal/config"
)

// WarnUnknownFlags writes warnings to stderr for flags that don't exist in
// restic's generated command metadata. Warnings are non-fatal and execution
// continues.
func WarnUnknownFlags(command string, flags []config.Flag) {
	warnUnknownFlags(os.Stderr, command, flags)
}

func warnUnknownFlags(w io.Writer, command string, flags []config.Flag) {
	unknown := unknownFlags(command, flags)
	if len(unknown) == 0 {
		return
	}

	commandLabel := command
	if commandLabel == "" {
		commandLabel = "global"
	}

	for _, flag := range unknown {
		_, _ = fmt.Fprintf(w, "warning: unknown restic flag %q for command %q\n", flag, commandLabel)
	}
}

func unknownFlags(command string, flags []config.Flag) []string {
	knownLong, knownAlias := knownOptionNames(command)
	seen := make(map[string]struct{})
	unknown := make([]string, 0)

	for _, flag := range flags {
		name := strings.TrimSpace(flag.Name)
		if name == "" {
			continue
		}

		normalized := strings.TrimLeft(name, "-")
		if normalized == "" {
			continue
		}

		known := false
		if len(normalized) == 1 {
			_, known = knownAlias[normalized]
			if !known {
				_, known = knownLong[normalized]
			}
		} else {
			_, known = knownLong[normalized]
		}

		if known {
			continue
		}

		if _, dup := seen[name]; dup {
			continue
		}
		seen[name] = struct{}{}
		unknown = append(unknown, name)
	}

	return unknown
}

func knownOptionNames(command string) (map[string]struct{}, map[string]struct{}) {
	long := make(map[string]struct{})
	alias := make(map[string]struct{})

	addOptions := func(opts []Option) {
		for _, opt := range opts {
			if opt.Name != "" {
				long[opt.Name] = struct{}{}
			}
			if opt.Alias != "" {
				alias[opt.Alias] = struct{}{}
			}
		}
	}

	if global, ok := Commands["global"]; ok {
		addOptions(global.Options)
	}
	if commandCfg, ok := Commands[command]; ok {
		addOptions(commandCfg.Options)
	}

	return long, alias
}
