package config

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// Config holds all server configuration derived from environment variables and flags.
type Config struct {
	Port             int
	Host             string
	DBPath           string
	GinMode          string
	CORSAllowOrigins string
	AutoMigrate      bool
	AdminToken       string
}

// LoadEnvFile reads a simple .env file if it exists and loads variables into environment without overriding existing ones.
func LoadEnvFile(filenames ...string) {
	if len(filenames) == 0 {
		filenames = []string{".env", "../.env"}
	}

	for _, filename := range filenames {
		file, err := os.Open(filename)
		if err != nil {
			continue
		}

		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			line := strings.TrimSpace(scanner.Text())
			if line == "" || strings.HasPrefix(line, "#") {
				continue
			}

			parts := strings.SplitN(line, "=", 2)
			if len(parts) != 2 {
				continue
			}

			key := strings.TrimSpace(parts[0])
			val := strings.TrimSpace(parts[1])
			// Strip optional surrounding quotes
			val = strings.Trim(val, `"'`)

			// Only set if not already present in environment
			if _, exists := os.LookupEnv(key); !exists {
				_ = os.Setenv(key, val)
			}
		}
		_ = file.Close()
	}
}

// Load reads and parses all configuration settings from the environment.
func Load() *Config {
	LoadEnvFile()

	cfg := &Config{
		Port:             8080,
		Host:             "0.0.0.0",
		DBPath:           "anl.db",
		GinMode:          "release",
		CORSAllowOrigins: "*",
		AutoMigrate:      true,
		AdminToken:       "",
	}

	if portStr := os.Getenv("PORT"); portStr != "" {
		if p, err := strconv.Atoi(portStr); err == nil && p > 0 {
			cfg.Port = p
		}
	}

	if hostStr := os.Getenv("HOST"); hostStr != "" {
		cfg.Host = hostStr
	}

	if dbPathStr := os.Getenv("DB_PATH"); dbPathStr != "" {
		cfg.DBPath = dbPathStr
	}

	if ginModeStr := os.Getenv("GIN_MODE"); ginModeStr != "" {
		cfg.GinMode = ginModeStr
	}

	if corsStr := os.Getenv("CORS_ALLOW_ORIGINS"); corsStr != "" {
		cfg.CORSAllowOrigins = corsStr
	}

	if token := os.Getenv("ADMIN_TOKEN"); token != "" {
		cfg.AdminToken = token
	}

	if autoMigrateStr := os.Getenv("AUTO_MIGRATE"); autoMigrateStr != "" {
		cfg.AutoMigrate = strings.ToLower(autoMigrateStr) != "false" && autoMigrateStr != "0"
	}

	return cfg
}

// Address returns the combined host:port address string.
func (c *Config) Address() string {
	return fmt.Sprintf("%s:%d", c.Host, c.Port)
}
