package webrtc

import (
	"strings"
	"testing"

	appcfg "github.com/datarhei/core/v16/restream/app"
)

func TestBuildArgs_CopyCodecs(t *testing.T) {
	cfg := appcfg.ConfigWebRTC{Enabled: true, VideoPT: 102, AudioPT: 111}
	got := BuildArgs(cfg, 49200)

	// Must contain -c:v copy and -c:a copy when ForceTranscode is false.
	if !contains(got, "-c:v", "copy") {
		t.Fatalf("expected -c:v copy, got %v", got)
	}
	if !contains(got, "-c:a", "copy") {
		t.Fatalf("expected -c:a copy, got %v", got)
	}

	// Two UDP addresses, one per track, with port+1 for audio.
	if !any(got, "udp://127.0.0.1:49200?") {
		t.Fatalf("expected video udp on 49200, got %v", got)
	}
	if !any(got, "udp://127.0.0.1:49201?") {
		t.Fatalf("expected audio udp on 49201, got %v", got)
	}

	// Payload types must be stringified.
	if !contains(got, "-payload_type", "102") {
		t.Fatalf("expected video PT 102, got %v", got)
	}
	if !contains(got, "-payload_type", "111") {
		t.Fatalf("expected audio PT 111, got %v", got)
	}
}

func TestBuildArgs_ForceTranscode(t *testing.T) {
	cfg := appcfg.ConfigWebRTC{Enabled: true, VideoPT: 102, AudioPT: 111, ForceTranscode: true}
	got := BuildArgs(cfg, 49200)

	if !contains(got, "-c:v", "libx264") {
		t.Fatalf("expected -c:v libx264, got %v", got)
	}
	if !contains(got, "-profile:v", "baseline") {
		t.Fatalf("expected baseline profile, got %v", got)
	}
	if !contains(got, "-c:a", "libopus") {
		t.Fatalf("expected -c:a libopus, got %v", got)
	}
}

func TestBuildArgs_TwoTrackBoundary(t *testing.T) {
	cfg := appcfg.ConfigWebRTC{Enabled: true, VideoPT: 102, AudioPT: 111}
	got := BuildArgs(cfg, 49200)

	// The second `-map` marks the start of the audio leg — the split
	// point restream.AppendOutput callers use.
	mapCount := 0
	for _, a := range got {
		if a == "-map" {
			mapCount++
		}
	}
	if mapCount != 2 {
		t.Fatalf("expected exactly 2 -map tokens, got %d in %v", mapCount, got)
	}
}

// contains reports whether the two-token sequence appears consecutively.
func contains(haystack []string, a, b string) bool {
	for i := 0; i+1 < len(haystack); i++ {
		if haystack[i] == a && haystack[i+1] == b {
			return true
		}
	}
	return false
}

// any reports whether any element of haystack starts with prefix.
func any(haystack []string, prefix string) bool {
	for _, h := range haystack {
		if strings.HasPrefix(h, prefix) {
			return true
		}
	}
	return false
}

// TestBuildArgs_DefaultMaps confirms 0:v:0 / 0:a:0 are emitted when
// VideoMap / AudioMap are empty (regression on the fix for issue #2 —
// the prior version had these as hardcoded literals; if VideoMap is
// ever empty unexpectedly, BuildArgs must still produce a working
// command line).
func TestBuildArgs_DefaultMaps(t *testing.T) {
	cfg := appcfg.ConfigWebRTC{Enabled: true, VideoPT: 102, AudioPT: 111}
	got := BuildArgs(cfg, 50000)
	if !contains(got, "-map", "0:v:0") {
		t.Fatalf("expected default video map 0:v:0, got %v", got)
	}
	if !contains(got, "-map", "0:a:0") {
		t.Fatalf("expected default audio map 0:a:0, got %v", got)
	}
}

// TestBuildArgs_CustomMaps drives the issue-#2 fix: when the user
// configures a multi-input pipeline (audio on input #1, etc.), the
// emitted -map values must follow the user's choice rather than the
// "0:v:0"/"0:a:0" assumption.
func TestBuildArgs_CustomMaps(t *testing.T) {
	cfg := appcfg.ConfigWebRTC{
		Enabled:  true,
		VideoPT:  102,
		AudioPT:  111,
		VideoMap: "0:v:1",
		AudioMap: "1:a:0",
	}
	got := BuildArgs(cfg, 50000)
	if !contains(got, "-map", "0:v:1") {
		t.Fatalf("expected custom video map 0:v:1, got %v", got)
	}
	if !contains(got, "-map", "1:a:0") {
		t.Fatalf("expected custom audio map 1:a:0, got %v", got)
	}
	// The default literals should NOT appear when overridden.
	for _, opt := range got {
		if opt == "0:v:0" || opt == "0:a:0" {
			t.Errorf("expected no default maps in output, found %q in %v", opt, got)
		}
	}
}
