package db

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

	_ "github.com/lib/pq"
)

var PgDB *sql.DB

// ConnectPostgres PostgreSQL veritabanına bağlanır.
func ConnectPostgres() (*sql.DB, error) {
	connStr := strings.TrimSpace(os.Getenv("POSTGRES_CONN"))
	if connStr == "" {
		return nil, fmt.Errorf("POSTGRES_CONN tanımlı değil")
	}

	db, err := sql.Open("postgres", connStr)
	if err != nil {
		return nil, fmt.Errorf("PostgreSQL bağlantı hatası: %w", err)
	}

	// Bağlantı havuzu ayarları (audit log uyumlu).
	db.SetMaxOpenConns(30)
	db.SetMaxIdleConns(10)
	db.SetConnMaxLifetime(30 * time.Minute)
	db.SetConnMaxIdleTime(5 * time.Minute)

	// Bağlantıyı test et.
	if err = db.Ping(); err != nil {
		// Some managed PostgreSQL servers require TLS. If the current DSN uses
		// sslmode=disable and server rejects with "no encryption", retry once
		// with sslmode=require to avoid startup failure.
		if strings.Contains(err.Error(), "no pg_hba.conf entry") &&
			strings.Contains(err.Error(), "no encryption") &&
			strings.Contains(strings.ToLower(connStr), "sslmode=disable") {
			secureConnStr := strings.Replace(connStr, "sslmode=disable", "sslmode=require", 1)
			log.Println("PostgreSQL TLS gerektiriyor, sslmode=require ile tekrar deneniyor")

			_ = db.Close()
			db, err = sql.Open("postgres", secureConnStr)
			if err != nil {
				return nil, fmt.Errorf("PostgreSQL TLS retry open failed: %w", err)
			}

			db.SetMaxOpenConns(30)
			db.SetMaxIdleConns(10)
			db.SetConnMaxLifetime(30 * time.Minute)
			db.SetConnMaxIdleTime(5 * time.Minute)

			if err = db.Ping(); err != nil {
				return nil, fmt.Errorf("PostgreSQL erişilemiyor (TLS retry): %w", err)
			}
		} else {
			return nil, fmt.Errorf("PostgreSQL erişilemiyor: %w", err)
		}
	}

	log.Println("PostgreSQL bağlantısı başarılı")
	PgDB = db
	return db, nil
}

// GetPostgresUsers test amaçlı ilk 5 kullanıcıyı listeler.
func GetPostgresUsers(db *sql.DB) error {
	query := `SELECT id, code, email FROM mk_dfusr ORDER BY id LIMIT 5`
	rows, err := db.Query(query)
	if err != nil {
		return fmt.Errorf("PostgreSQL sorgu hatası: %w", err)
	}
	defer rows.Close()

	fmt.Println("İlk 5 PostgreSQL kullanıcısı:")
	for rows.Next() {
		var id int
		var code, email string
		if err := rows.Scan(&id, &code, &email); err != nil {
			return err
		}
		fmt.Printf("  -> ID: %-4d | USER: %-20s | EMAIL: %s\n", id, code, email)
	}

	return rows.Err()
}
