package db

import (
	"context"
	"fmt"
	"time"

	"github.com/jackc/pgx/v5/pgxpool"
)

// 默认连接池配置：10–50 用户私部署量级够用；超出后再按实际负载调整。
const (
	defaultMaxConns              = 20
	defaultMinConns              = 2
	defaultMaxConnLifetime       = time.Hour                   // 单连接最大寿命，到点后回收重建
	defaultMaxConnLifetimeJitter = defaultMaxConnLifetime / 10 // 在寿命基础上叠加 0~6 分钟随机抖动，防同步重建 storm
	defaultPingTimeout           = 5 * time.Second
	defaultHealthTimeout         = time.Second
)

// Pool 是 pgxpool.Pool 的类型别名，外部代码可直接以 db.Pool 表达连接池类型，
// 同时保留 pgx 原生方法（Acquire/Exec/Query/...）。
type Pool = pgxpool.Pool

// NewPool 根据 dsn 构建 Postgres 连接池，并在返回前用 5s 超时的 Ping 做健康验证。
// 失败时关闭已创建的池并返回错误，避免泄露资源。
func NewPool(ctx context.Context, dsn string) (*Pool, error) {
	cfg, err := pgxpool.ParseConfig(dsn)
	if err != nil {
		return nil, fmt.Errorf("parse dsn: %w", err)
	}
	cfg.MaxConns = defaultMaxConns
	cfg.MinConns = defaultMinConns
	cfg.MaxConnLifetime = defaultMaxConnLifetime
	cfg.MaxConnLifetimeJitter = defaultMaxConnLifetimeJitter

	pool, err := pgxpool.NewWithConfig(ctx, cfg)
	if err != nil {
		return nil, fmt.Errorf("new pool: %w", err)
	}

	pingCtx, cancel := context.WithTimeout(ctx, defaultPingTimeout)
	defer cancel()
	if err := pool.Ping(pingCtx); err != nil {
		pool.Close()
		return nil, fmt.Errorf("ping: %w", err)
	}
	return pool, nil
}

// HealthCheck 用 1s 超时探测数据库连通性，供 healthz/readyz 等探针调用。
func HealthCheck(ctx context.Context, pool *Pool) error {
	c, cancel := context.WithTimeout(ctx, defaultHealthTimeout)
	defer cancel()
	return pool.Ping(c)
}
