package database

import (
	"context"
	"testing"
	"time"
)

func TestNewClient_InvalidDSN(t *testing.T) {
	t.Parallel()

	cfg := Config{
		DSN:            "invalid-dsn",
		MaxConnections: 10,
		MaxIdleConns:   5,
	}

	client, err := NewClient(cfg)
	if err == nil {
		if client != nil {
			_ = client.Close()
		}
		t.Error("Expected error for invalid DSN, got nil")
	}
}

func TestNewClient_ValidConfig(t *testing.T) {
	t.Parallel()

	// This test requires a real database connection
	// Skip if DSN is not set
	dsn := "postgres://goplt:goplt_password@localhost:5432/goplt?sslmode=disable"
	if testing.Short() {
		t.Skip("Skipping database test in short mode")
	}

	cfg := Config{
		DSN:             dsn,
		MaxConnections:  10,
		MaxIdleConns:    5,
		ConnMaxLifetime: 5 * time.Minute,
		ConnMaxIdleTime: 10 * time.Minute,
	}

	client, err := NewClient(cfg)
	if err != nil {
		t.Skipf("Skipping test - database not available: %v", err)
	}
	defer func() {
		if err := client.Close(); err != nil {
			t.Logf("Failed to close client: %v", err)
		}
	}()

	if client == nil {
		t.Fatal("Expected client, got nil")
	}

	if client.Client == nil {
		t.Error("Expected Ent client, got nil")
	}

	if client.db == nil {
		t.Error("Expected sql.DB, got nil")
	}
}

func TestClient_Ping(t *testing.T) {
	t.Parallel()

	dsn := "postgres://goplt:goplt_password@localhost:5432/goplt?sslmode=disable"
	if testing.Short() {
		t.Skip("Skipping database test in short mode")
	}

	cfg := Config{
		DSN:            dsn,
		MaxConnections: 10,
		MaxIdleConns:   5,
	}

	client, err := NewClient(cfg)
	if err != nil {
		t.Skipf("Skipping test - database not available: %v", err)
	}
	defer func() {
		if err := client.Close(); err != nil {
			t.Logf("Failed to close client: %v", err)
		}
	}()

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := client.Ping(ctx); err != nil {
		t.Errorf("Ping failed: %v", err)
	}
}

func TestClient_Close(t *testing.T) {
	t.Parallel()

	dsn := "postgres://goplt:goplt_password@localhost:5432/goplt?sslmode=disable"
	if testing.Short() {
		t.Skip("Skipping database test in short mode")
	}

	cfg := Config{
		DSN:            dsn,
		MaxConnections: 10,
		MaxIdleConns:   5,
	}

	client, err := NewClient(cfg)
	if err != nil {
		t.Skipf("Skipping test - database not available: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := client.Close(); err != nil {
		t.Errorf("Close failed: %v", err)
	}

	// Ping should fail after close
	if err := client.Ping(ctx); err == nil {
		t.Error("Expected Ping to fail after Close, got nil error")
	}
}

func TestClient_DB(t *testing.T) {
	t.Parallel()

	dsn := "postgres://goplt:goplt_password@localhost:5432/goplt?sslmode=disable"
	if testing.Short() {
		t.Skip("Skipping database test in short mode")
	}

	cfg := Config{
		DSN:            dsn,
		MaxConnections: 10,
		MaxIdleConns:   5,
	}

	client, err := NewClient(cfg)
	if err != nil {
		t.Skipf("Skipping test - database not available: %v", err)
	}
	defer func() {
		if err := client.Close(); err != nil {
			t.Logf("Failed to close client: %v", err)
		}
	}()

	db := client.DB()
	if db == nil {
		t.Error("Expected sql.DB from DB(), got nil")
	}
}
