package config

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

type Config struct {
	AppPort string

	DBHost      string
	DBPort      string
	DBName      string
	DBUser      string
	DBPass      string
	DBCharset   string
	DBParseTime string
	DBLoc       string
}

func Load(envPath string) (*Config, error) {
	if envPath != "" {
		_ = loadDotEnv(envPath)
	}

	cfg := &Config{
		AppPort:     getEnv("APP_PORT", "8095"),
		DBHost:      getEnv("DB_HOST", "127.0.0.1"),
		DBPort:      getEnv("DB_PORT", "3306"),
		DBName:      getEnv("DB_NAME", ""),
		DBUser:      getEnv("DB_USER", ""),
		DBPass:      getEnv("DB_PASS", ""),
		DBCharset:   getEnv("DB_CHARSET", "utf8mb4"),
		DBParseTime: getEnv("DB_PARSE_TIME", "true"),
		DBLoc:       getEnv("DB_LOC", "Asia%2FBangkok"),
	}

	if strings.TrimSpace(cfg.DBName) == "" {
		return nil, fmt.Errorf("DB_NAME is required")
	}
	if strings.TrimSpace(cfg.DBUser) == "" {
		return nil, fmt.Errorf("DB_USER is required")
	}

	return cfg, nil
}

func (c *Config) MySQLDSN() string {
	return fmt.Sprintf(
		"%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=%s&loc=%s",
		c.DBUser,
		c.DBPass,
		c.DBHost,
		c.DBPort,
		c.DBName,
		c.DBCharset,
		c.DBParseTime,
		c.DBLoc,
	)
}

func getEnv(key, fallback string) string {
	v := strings.TrimSpace(os.Getenv(key))
	if v == "" {
		return fallback
	}
	return v
}

func loadDotEnv(path string) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	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])
		val = strings.Trim(val, `"'`)

		if _, exists := os.LookupEnv(key); !exists {
			_ = os.Setenv(key, val)
		}
	}

	return scanner.Err()
}