package config

import (
	"fmt"
	"log/slog"
	"path/filepath"
	"slices"
	"strings"
)

func checkCollectorRefs(collectorRefs []string, ctx string) error {
	// At least one collector, no duplicates
	if len(collectorRefs) == 0 {
		return fmt.Errorf("no collectors defined for %s", ctx)
	}
	for i, ci := range collectorRefs {
		if slices.Contains(collectorRefs[i+1:], ci) {
			return fmt.Errorf("duplicate collector reference %q in %s", ci, ctx)
		}
	}
	return nil
}

func resolveCollectorRefs(
	collectorRefs []string, collectors map[string]*CollectorConfig, ctx string,
) ([]*CollectorConfig, error) {
	resolved := make([]*CollectorConfig, 0, len(collectorRefs))
	found := make(map[*CollectorConfig]bool)
	for _, cref := range collectorRefs {
		crefResolved := false
		for k, c := range collectors {
			matched, err := filepath.Match(cref, k)
			if err != nil {
				return nil, fmt.Errorf("bad collector %q referenced in %s: %w", cref, ctx, err)
			}
			if matched && !found[c] {
				resolved = append(resolved, c)
				found[c] = true
				crefResolved = true
			}
		}
		if !crefResolved {
			return nil, fmt.Errorf("unknown collector %q referenced in %s", cref, ctx)
		}
	}
	slog.Debug("Resolved collectors", "context", ctx, "count", len(resolved))
	return resolved, nil
}

func checkLabel(label string, ctx ...string) error {
	if label == "" {
		return fmt.Errorf("empty label defined in %s", strings.Join(ctx, " "))
	}
	if label == "job" || label == TargetLabel {
		return fmt.Errorf("reserved label %q redefined in %s", label, strings.Join(ctx, " "))
	}
	return nil
}

func checkOverflow(m map[string]any, ctx string) error {
	if len(m) > 0 {
		var keys []string
		for k := range m {
			keys = append(keys, k)
		}
		return fmt.Errorf("unknown fields in %s: %s", ctx, strings.Join(keys, ", "))
	}
	return nil
}
