package dbutil

import (
	"database/sql"
	"fmt"
	"log"
	"time"

	_ "github.com/lib/pq"
)

// The dbutil package provides an interface between go code and a relational database.

var db *sql.DB

// ConnConfig holds everything Init needs to open the Postgres connection pool.
// The app builds it from its own config (dbutil.ConnConfig{Username: cfg.X, ...})
// so the framework never imports application config.
type ConnConfig struct {
	Username       string
	Password       string
	Host           string
	Port           int
	Name           string
	Schema         string
	SSLMode        string
	MaxConns       int
	TimeoutSeconds int
}

// BuildConnectionString renders a lib/pq Postgres DSN with the session TimeZone
// pinned to UTC. Exported so cmd/migrate reuses it instead of duplicating the
// format string.
func BuildConnectionString(c ConnConfig) string {
	return fmt.Sprintf("postgres://%s:%s@%s:%d/%s?search_path=%s&sslmode=%s&options=-c%%20TimeZone%%3DUTC",
		c.Username,
		c.Password,
		c.Host,
		c.Port,
		c.Name,
		c.Schema,
		c.SSLMode,
	)
}

// Init opens the global connection pool from c and pings it. It fatals on
// failure, matching the previous package behaviour.
func Init(c ConnConfig) {
	var err error
	db, err = sql.Open("postgres", BuildConnectionString(c))
	if err != nil {
		log.Fatal(err.Error())
	}

	if pingErr := db.Ping(); pingErr != nil {
		log.Fatal(pingErr.Error())
	}

	db.SetMaxOpenConns(c.MaxConns)
	db.SetMaxIdleConns(2)
	db.SetConnMaxIdleTime(time.Duration(c.TimeoutSeconds) * time.Second)
}

func DB() *sql.DB { return db }
