// Package db provides PostgreSQL connection management using pgx.
package db

import (
	"context"
	"fmt"
	"log/slog"
	"time"

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

// Pool wraps a pgx connection pool with lifecycle helpers.
type Pool struct {
	*pgxpool.Pool
}

// New creates a connection pool from a PostgreSQL DSN.
func New(dsn string) (*Pool, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	cfg, err := pgxpool.ParseConfig(dsn)
	if err != nil {
		return nil, fmt.Errorf("parse pgx config: %w", err)
	}

	// Sensible defaults
	cfg.MaxConns = 20
	cfg.MinConns = 2
	cfg.MaxConnLifetime = 30 * time.Minute
	cfg.MaxConnIdleTime = 10 * time.Minute
	cfg.HealthCheckPeriod = 5 * time.Second

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

	if err := pool.Ping(ctx); err != nil {
		pool.Close()
		return nil, fmt.Errorf("ping database: %w", err)
	}

	slog.Info("database connected", "pool", cfg.ConnConfig.Database)
	return &Pool{Pool: pool}, nil
}

// Close shuts down the pool gracefully.
func (p *Pool) Close() {
	if p.Pool != nil {
		p.Pool.Close()
		slog.Info("database pool closed")
	}
}

// Health returns nil if the database is reachable.
func (p *Pool) Health(ctx context.Context) error {
	ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
	defer cancel()
	return p.Ping(ctx)
}
