package webrtc

import (
	"context"
	"testing"
	"time"

	"github.com/pion/webrtc/v4"
)

// minimalOfferSDP returns an SDP offer that advertises H.264 (video) and
// Opus (audio) as recvonly — the minimum a WHEP client sends.
func minimalOfferSDP(t *testing.T) webrtc.SessionDescription {
	t.Helper()
	// Create a throwaway PC to generate a valid offer.
	me := &webrtc.MediaEngine{}
	if err := me.RegisterDefaultCodecs(); err != nil {
		t.Fatalf("RegisterDefaultCodecs: %v", err)
	}
	api := webrtc.NewAPI(webrtc.WithMediaEngine(me))
	pc, err := api.NewPeerConnection(webrtc.Configuration{})
	if err != nil {
		t.Fatalf("NewPeerConnection: %v", err)
	}
	defer pc.Close()

	if _, err := pc.AddTransceiverFromKind(webrtc.RTPCodecTypeVideo,
		webrtc.RTPTransceiverInit{Direction: webrtc.RTPTransceiverDirectionRecvonly}); err != nil {
		t.Fatalf("AddTransceiver video: %v", err)
	}
	if _, err := pc.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio,
		webrtc.RTPTransceiverInit{Direction: webrtc.RTPTransceiverDirectionRecvonly}); err != nil {
		t.Fatalf("AddTransceiver audio: %v", err)
	}
	offer, err := pc.CreateOffer(nil)
	if err != nil {
		t.Fatalf("CreateOffer: %v", err)
	}
	return offer
}

func TestPeerFactory_CreateAnswer(t *testing.T) {
	src, err := NewSource("streamA", 0)
	if err != nil {
		t.Fatalf("NewSource: %v", err)
	}
	defer src.Close()
	src.Start()

	cfg := DefaultConfig()
	factory, err := NewPeerFactory(cfg)
	if err != nil {
		t.Fatalf("NewPeerFactory: %v", err)
	}

	offer := minimalOfferSDP(t)

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

	peer, err := factory.CreatePeer(ctx, src, offer)
	if err != nil {
		t.Fatalf("CreatePeer: %v", err)
	}
	defer peer.Close()

	if peer.Answer().Type != webrtc.SDPTypeAnswer {
		t.Errorf("Answer().Type = %v, want answer", peer.Answer().Type)
	}
	if peer.ResourceID() == "" {
		t.Error("ResourceID should be non-empty")
	}
}

func TestPeerFactory_ClosesCleanly(t *testing.T) {
	src, _ := NewSource("streamA", 0)
	defer src.Close()
	src.Start()

	factory, _ := NewPeerFactory(DefaultConfig())
	offer := minimalOfferSDP(t)

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	peer, err := factory.CreatePeer(ctx, src, offer)
	if err != nil {
		t.Fatalf("CreatePeer: %v", err)
	}
	if err := peer.Close(); err != nil {
		t.Errorf("Close: %v", err)
	}
	// Second close should be a no-op, not panic.
	if err := peer.Close(); err != nil {
		t.Errorf("second Close: %v", err)
	}
}
