package config

import (
	"fmt"
	"strings"

	"github.com/go-sql-driver/mysql"
)

// pqValue는 lib/pq key=value 접속 문자열의 값을 안전하게 인용합니다.
// 공백·따옴표·백슬래시가 있으면 작은따옴표로 감싸고 내부의 \ 와 ' 를 이스케이프합니다.
func pqValue(v string) string {
	if v != "" && !strings.ContainsAny(v, " '\\") {
		return v
	}
	v = strings.ReplaceAll(v, `\`, `\\`)
	v = strings.ReplaceAll(v, `'`, `\'`)
	return "'" + v + "'"
}

// PostgresDSN은 구조화된 db 설정에서 lib/pq DSN을 조립합니다. db가 없으면 dsn 문자열 폴백.
func (s ServiceConfig) PostgresDSN() string {
	c := s.DB
	if c == nil {
		return s.DSN
	}
	host, port, dbname, ssl := c.Host, c.Port, c.DBName, c.SSLMode
	if host == "" {
		host = "localhost"
	}
	if port == 0 {
		port = 5432
	}
	if dbname == "" {
		dbname = "postgres"
	}
	if ssl == "" {
		ssl = "disable"
	}
	return fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
		pqValue(host), port, pqValue(c.User), pqValue(c.Password), pqValue(dbname), pqValue(ssl))
}

// MySQLDSN은 구조화된 db 설정에서 go-sql-driver DSN을 조립합니다. db가 없으면 dsn 문자열 폴백.
// FormatDSN을 사용하므로 비밀번호의 특수문자(@, /, : 등)도 안전합니다.
func (s ServiceConfig) MySQLDSN() string {
	c := s.DB
	if c == nil {
		return s.DSN
	}
	host, port := c.Host, c.Port
	if host == "" {
		host = "localhost"
	}
	if port == 0 {
		port = 3306
	}
	mc := mysql.NewConfig()
	mc.User = c.User
	mc.Passwd = c.Password
	mc.Net = "tcp"
	mc.Addr = fmt.Sprintf("%s:%d", host, port)
	mc.DBName = c.DBName
	return mc.FormatDSN()
}
