package streamchecker

import (
	"context"
	"fmt"
	"log/slog"
	"net/http"
	"time"
)

type Checker struct {
	streamURL string
	client    *http.Client
	userAgent string
}

// Option represents a functional option for configuring the Checker
type Option func(*Checker)

// WithUserAgent sets a custom User-Agent header
func WithUserAgent(userAgent string) Option {
	return func(c *Checker) {
		c.userAgent = userAgent
	}
}

// New creates a new stream checker with sensible defaults
func New(streamURL string, opts ...Option) *Checker {
	c := &Checker{
		streamURL: streamURL,
		client: &http.Client{
			Timeout: 10 * time.Second,
		},
	}

	// Apply any provided options
	for _, opt := range opts {
		opt(c)
	}

	return c
}

// IsLive checks if the stream is currently broadcasting
func (c *Checker) IsLive() (bool, error) {
	return c.IsLiveWithContext(context.Background())
}

// IsLiveWithContext checks if the stream is live using the provided context
func (c *Checker) IsLiveWithContext(ctx context.Context) (bool, error) {
	slog.Debug("Checking stream status", "url", c.streamURL)

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.streamURL, nil)
	if err != nil {
		return false, fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("User-Agent", c.userAgent)

	resp, err := c.client.Do(req)
	if err != nil {
		slog.Debug("Connection to stream failed, considering not live", "error", err)
		return false, nil // Connection failures mean the stream is not available
	}
	defer func() {
		if err := resp.Body.Close(); err != nil {
			slog.Error("Failed to close response body", "error", err)
		}
	}()

	if resp.StatusCode == http.StatusOK {
		slog.Info("Stream is live", "status", resp.StatusCode)
		return true, nil
	}

	slog.Debug("Stream is not live", "status", resp.StatusCode)
	return false, nil
}

// GetStreamURL returns the URL being monitored
func (c *Checker) GetStreamURL() string {
	return c.streamURL
}
