package redis

import (
	"context"
	"fmt"
	"time"

	"github.com/redis/go-redis/v9"

	"bit.admedia.com/scm/ad/adpilot-indexing-commit-intel.com/internal/config"
)

const readyTimeout = 2 * time.Second

// Client wraps a Redis connection for health checks and stream operations.
type Client struct {
	client *redis.Client
}

// New creates a Redis client from configuration. URL parsing is validated; Redis
// does not need to be reachable at startup.
func New(cfg config.RedisConfig) (*Client, error) {
	opts, err := redis.ParseURL(cfg.URL)
	if err != nil {
		return nil, fmt.Errorf("parse redis url: %w", err)
	}

	if opts.DialTimeout == 0 {
		opts.DialTimeout = 5 * time.Second
	}
	if opts.ReadTimeout == 0 {
		opts.ReadTimeout = 3 * time.Second
	}
	if opts.WriteTimeout == 0 {
		opts.WriteTimeout = 3 * time.Second
	}

	return &Client{client: redis.NewClient(opts)}, nil
}

// Ping checks Redis connectivity.
func (c *Client) Ping(ctx context.Context) error {
	return c.client.Ping(ctx).Err()
}

// Ready reports whether Redis responds to PING within a short timeout.
func (c *Client) Ready(ctx context.Context) bool {
	if c == nil || c.client == nil {
		return false
	}

	ctx, cancel := context.WithTimeout(ctx, readyTimeout)
	defer cancel()

	return c.Ping(ctx) == nil
}

// Close releases the Redis connection pool.
func (c *Client) Close() error {
	if c == nil || c.client == nil {
		return nil
	}
	return c.client.Close()
}

// Underlying returns the go-redis client for stream operations.
func (c *Client) Underlying() *redis.Client {
	if c == nil {
		return nil
	}
	return c.client
}
