package envfile

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"strings"

	"coopcloud.tech/abra/pkg/log"
	"git.coopcloud.tech/coop-cloud/godotenv"
)

// envVarModifiers is a list of env var modifier strings. These are added to
// env vars as comments and modify their processing by Abra, e.g. determining
// how long secrets should be.
var envVarModifiers = []string{"length"}

// AppEnv is a map of the values in an apps env config
type AppEnv = map[string]string

// AppModifiers is a map of modifiers in an apps env config
type AppModifiers = map[string]map[string]string

// ReadEnv loads an app envivornment into a map.
func ReadEnv(filePath string) (AppEnv, error) {
	var envVars AppEnv

	envVars, _, err := godotenv.Read(filePath)
	if err != nil {
		return nil, err
	}

	log.Debugf("read %s from %s", envVars, filePath)

	return envVars, nil
}

// ReadEnv loads an app envivornment and their modifiers in two different maps.
func ReadEnvWithModifiers(filePath string) (AppEnv, AppModifiers, error) {
	var envVars AppEnv

	envVars, mods, err := godotenv.Read(filePath)
	if err != nil {
		return nil, mods, err
	}

	log.Debugf("read %s from %s", envVars, filePath)

	return envVars, mods, nil
}

// ReadAbraShEnvVars reads env vars from an abra.sh recipe file.
func ReadAbraShEnvVars(abraSh string) (map[string]string, error) {
	envVars := make(map[string]string)

	file, err := os.Open(abraSh)
	if err != nil {
		if os.IsNotExist(err) {
			return envVars, nil
		}
		return envVars, err
	}
	defer file.Close()

	exportRegex, err := regexp.Compile(`^export\s+(\w+=\w+)`)
	if err != nil {
		return envVars, err
	}

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		txt := scanner.Text()
		if exportRegex.MatchString(txt) {
			splitVals := strings.Split(txt, "export ")
			envVarDef := splitVals[len(splitVals)-1]
			keyVal := strings.Split(envVarDef, "=")
			if len(keyVal) != 2 {
				return envVars, fmt.Errorf("couldn't parse %s", txt)
			}
			envVars[keyVal[0]] = keyVal[1]
		}
	}

	if len(envVars) > 0 {
		log.Debugf("read %s from %s", envVars, abraSh)
	} else {
		log.Debugf("read 0 env var exports from %s", abraSh)
	}

	return envVars, nil
}

type EnvVar struct {
	Name    string
	Present bool
}