package adapters

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

const (
	// videoDownloadTimeout is the timeout for downloading video from URI.
	videoDownloadTimeout = 60 * time.Second

	// maxVideoSize is the maximum video size to download (500MB).
	maxVideoSize = 500 * 1024 * 1024
)

// downloadVideo fetches video bytes from a URL, streaming to a temp file first.
// Uses explicit timeout and size limit (500MB) to prevent hangs and OOM.
func downloadVideo(ctx context.Context, url string) ([]byte, error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return nil, fmt.Errorf("create request: %w", err)
	}

	// Use client with explicit timeout (never use http.DefaultClient)
	httpClient := &http.Client{Timeout: videoDownloadTimeout}
	resp, err := httpClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("fetch video: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unexpected status %d", resp.StatusCode)
	}

	// Stream to temp file to avoid OOM on large videos
	tmpFile, err := os.CreateTemp("", "video-*.mp4")
	if err != nil {
		return nil, fmt.Errorf("create temp file: %w", err)
	}
	defer os.Remove(tmpFile.Name())
	defer tmpFile.Close()

	// Limit to maxVideoSize
	limitedReader := io.LimitReader(resp.Body, maxVideoSize)

	written, err := io.Copy(tmpFile, limitedReader)
	if err != nil {
		return nil, fmt.Errorf("write video to temp: %w", err)
	}

	if written == maxVideoSize {
		return nil, fmt.Errorf("video exceeds %dMB limit", maxVideoSize/(1024*1024))
	}

	// Seek back and read
	if _, err := tmpFile.Seek(0, 0); err != nil {
		return nil, fmt.Errorf("seek temp file: %w", err)
	}

	data, err := io.ReadAll(tmpFile)
	if err != nil {
		return nil, fmt.Errorf("read temp file: %w", err)
	}

	return data, nil
}
