package settings

import (
	"os"
	"strconv"
)

var globalSetting *Setting

type Setting struct {
	values map[string]interface{}
}

func New(configPath string) (*Setting, error) {
	s := &Setting{
		values: make(map[string]interface{}),
	}

	// Try to load from environment variables with prefix
	prefix := "SAFELINE_"
	for _, env := range os.Environ() {
		key := env
		val := ""
		for i := 0; i < len(env); i++ {
			if env[i] == '=' {
				key = env[:i]
				val = env[i+1:]
				break
			}
		}
		if len(key) > len(prefix) && key[:len(prefix)] == prefix {
			s.values[key[len(prefix):]] = val
		}
	}

	// Also load from config file if it exists
	if _, err := os.Stat(configPath); err == nil {
		data, err := os.ReadFile(configPath)
		if err == nil {
			// Simple line-by-line parsing for YAML-like config
			lines := splitLines(string(data))
			for _, line := range lines {
				if len(line) == 0 || line[0] == '#' {
					continue
				}
				for i := 0; i < len(line); i++ {
					if line[i] == ':' {
						key := trimSpace(line[:i])
						val := trimSpace(line[i+1:])
						if len(val) >= 2 && val[0] == '"' && val[len(val)-1] == '"' {
							val = val[1 : len(val)-1]
						}
						s.values[key] = val
						break
					}
				}
			}
		}
	}

	globalSetting = s
	return s, nil
}

func Unmarshal(key string, dest interface{}) error {
	if globalSetting == nil {
		return nil
	}
	return globalSetting.Unmarshal(key, dest)
}

func (s *Setting) Unmarshal(key string, dest interface{}) error {
	if val, ok := s.values[key]; ok {
		switch v := dest.(type) {
		case *string:
			*v, _ = val.(string)
		case *int:
			if str, ok := val.(string); ok {
				*v, _ = strconv.Atoi(str)
			}
		case *bool:
			if str, ok := val.(string); ok {
				*v = str == "true" || str == "1"
			}
		}
	}
	return nil
}

func (s *Setting) Get(key string, defaultVal interface{}) interface{} {
	if val, ok := s.values[key]; ok {
		return val
	}
	return defaultVal
}

func (s *Setting) GetString(key, defaultVal string) string {
	if val, ok := s.values[key]; ok {
		if str, ok := val.(string); ok {
			return str
		}
	}
	return defaultVal
}

func (s *Setting) GetInt(key string, defaultVal int) int {
	if val, ok := s.values[key]; ok {
		if str, ok := val.(string); ok {
			if i, err := strconv.Atoi(str); err == nil {
				return i
			}
		}
	}
	return defaultVal
}

func (s *Setting) GetBool(key string, defaultVal bool) bool {
	if val, ok := s.values[key]; ok {
		if str, ok := val.(string); ok {
			return str == "true" || str == "1"
		}
	}
	return defaultVal
}

func splitLines(s string) []string {
	var lines []string
	start := 0
	for i := 0; i < len(s); i++ {
		if s[i] == '\n' {
			lines = append(lines, s[start:i])
			start = i + 1
		}
	}
	if start < len(s) {
		lines = append(lines, s[start:])
	}
	return lines
}

func trimSpace(s string) string {
	start := 0
	end := len(s)
	for start < end && (s[start] == ' ' || s[start] == '\t') {
		start++
	}
	for end > start && (s[end-1] == ' ' || s[end-1] == '\t') {
		end--
	}
	return s[start:end]
}
