package config

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"gopkg.in/yaml.v3"
)

type contextConfigKey struct{}

// ContextConfigKey is the context key for the configuration.
// nolint:gochecknoglobals // this is a context key
var ContextConfigKey = contextConfigKey{}

// FromContext returns the configuration from the context.
func FromContext(ctx context.Context) (*Config, error) {
	cfg, ok := ctx.Value(ContextConfigKey).(*Config)
	if !ok {
		return nil, fmt.Errorf("failed to get config from context")
	}

	return cfg, nil
}

// Config is the frizbee configuration.
type Config struct {
	GHActions GHActions `yaml:"ghactions" mapstructure:"ghactions"`
}

// GHActions is the GitHub Actions configuration.
type GHActions struct {
	Filter `yaml:",inline" mapstructure:",inline"`
}

// Filter is a common configuration for filtering out patterns.
type Filter struct {
	// Exclude is a list of patterns to exclude.
	Exclude []string `yaml:"exclude" mapstructure:"exclude"`
}

// ParseConfigFile parses a configuration file.
func ParseConfigFile(configfile string) (*Config, error) {
	cfg := &Config{}
	cleancfgfile := filepath.Clean(configfile)
	cfgF, err := os.Open(cleancfgfile)
	if err != nil {
		if os.IsNotExist(err) {
			return cfg, nil
		}

		return nil, fmt.Errorf("failed to open config file: %w", err)
	}
	// nolint:errcheck // we don't care about the error here
	defer cfgF.Close()

	dec := yaml.NewDecoder(cfgF)

	if err := dec.Decode(cfg); err != nil {
		return nil, fmt.Errorf("failed to decode config file: %w", err)
	}

	return cfg, nil
}
