package stream

import (
	"strings"
	"testing"

	"github.com/eduard256/Strix/internal/models"
)

// mockLogger implements the logger interface for testing
type mockLogger struct{}

func (m *mockLogger) Debug(msg string, args ...any) {}
func (m *mockLogger) Error(msg string, err error, args ...any) {}

// TestCurrentDeduplicationProblems демонстрирует проблемы текущей дедупликации
func TestCurrentDeduplicationProblems(t *testing.T) {
	logger := &mockLogger{}
	builder := NewBuilder([]string{}, logger)

	tests := []struct {
		name               string
		entry              models.CameraEntry
		ctx                BuildContext
		expectedURLCount   int // Сколько Builder генерирует
		realUniqueCount    int // Сколько реально уникальных
		description        string
	}{
		{
			name: "HTTP auth variants - same endpoint, 4 different URLs",
			entry: models.CameraEntry{
				Type:     "JPEG",
				Protocol: "http",
				Port:     80,
				URL:      "snapshot.jpg",
			},
			ctx: BuildContext{
				IP:       "192.168.1.100",
				Username: "admin",
				Password: "12345",
				Port:     80,
			},
			expectedURLCount: 4, // Builder генерирует 4 варианта
			realUniqueCount:  1, // Но это ОДИН поток
			description:      "PROBLEM: 4 authentication variants of the same HTTP endpoint",
		},
		{
			name: "HTTP with auth placeholders - generates duplicates",
			entry: models.CameraEntry{
				Type:     "JPEG",
				Protocol: "http",
				Port:     80,
				URL:      "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]",
			},
			ctx: BuildContext{
				IP:       "192.168.1.100",
				Username: "admin",
				Password: "12345",
				Port:     80,
			},
			expectedURLCount: 4,
			realUniqueCount:  1,
			description:      "PROBLEM: Placeholder replacement + auth variants = duplicates",
		},
		{
			name: "RTSP with credentials - now FIXED",
			entry: models.CameraEntry{
				Type:     "FFMPEG",
				Protocol: "rtsp",
				Port:     554,
				URL:      "/live/main",
			},
			ctx: BuildContext{
				IP:       "192.168.1.100",
				Username: "admin",
				Password: "12345",
				Port:     554,
			},
			expectedURLCount: 1, // FIXED: только с credentials
			realUniqueCount:  1, // Это один поток
			description:      "FIXED: RTSP with credentials generates ONLY auth URL",
		},
		{
			name: "RTSP without credentials - only one URL",
			entry: models.CameraEntry{
				Type:     "FFMPEG",
				Protocol: "rtsp",
				Port:     554,
				URL:      "/live/main",
			},
			ctx: BuildContext{
				IP:       "192.168.1.100",
				Username: "",
				Password: "",
				Port:     554,
			},
			expectedURLCount: 1,
			realUniqueCount:  1,
			description:      "OK: No credentials = only one URL",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			urls := builder.BuildURLsFromEntry(tt.entry, tt.ctx)

			t.Logf("\n=== %s ===", tt.description)
			t.Logf("Entry: %s://%s", tt.entry.Protocol, tt.entry.URL)
			t.Logf("Expected URL count: %d", tt.expectedURLCount)
			t.Logf("Real unique streams: %d", tt.realUniqueCount)
			t.Logf("Generated URLs:")
			for i, url := range urls {
				t.Logf("  [%d] %s", i+1, url)
			}

			if len(urls) != tt.expectedURLCount {
				t.Errorf("FAILED: Expected %d URLs, got %d", tt.expectedURLCount, len(urls))
			}

			// Демонстрация проблемы
			if len(urls) > tt.realUniqueCount {
				duplicateCount := len(urls) - tt.realUniqueCount
				t.Logf("\n⚠️  PROBLEM: %d semantic duplicates generated", duplicateCount)
				t.Logf("These are different URL strings pointing to the SAME stream!")
				t.Logf("Waste: %d unnecessary tests", duplicateCount)
			} else if len(urls) == tt.realUniqueCount && tt.expectedURLCount == tt.realUniqueCount {
				t.Logf("\n✓ NO DUPLICATES: All URLs are unique (FIXED!)")
			}

			// Показать канонические URL
			canonicalURLs := make(map[string][]string)
			for _, url := range urls {
				canonical := makeCanonical(url)
				canonicalURLs[canonical] = append(canonicalURLs[canonical], url)
			}

			t.Logf("\nCanonical URL analysis:")
			for canonical, variants := range canonicalURLs {
				t.Logf("  Canonical: %s", canonical)
				if len(variants) > 1 {
					t.Logf("    ⚠️  Has %d variants (DUPLICATES!):", len(variants))
					for _, v := range variants {
						t.Logf("      - %s", v)
					}
				} else {
					t.Logf("    ✓ Unique")
				}
			}
		})
	}
}

// TestMultipleSourcesDuplication тестирует дубликаты от разных источников
func TestMultipleSourcesDuplication(t *testing.T) {
	logger := &mockLogger{}
	builder := NewBuilder([]string{}, logger)

	// Симуляция: один и тот же паттерн из двух источников
	entry1 := models.CameraEntry{
		Type:     "FFMPEG",
		Protocol: "rtsp",
		Port:     554,
		URL:      "/Streaming/Channels/101",
	}

	entry2 := models.CameraEntry{
		Type:     "FFMPEG",
		Protocol: "rtsp",
		Port:     554,
		URL:      "/Streaming/Channels/101",
	}

	ctx := BuildContext{
		IP:       "192.168.1.100",
		Username: "admin",
		Password: "12345",
		Port:     554,
	}

	urls1 := builder.BuildURLsFromEntry(entry1, ctx)
	urls2 := builder.BuildURLsFromEntry(entry2, ctx)

	t.Logf("\n=== Multiple Sources Generate Same URLs ===")
	t.Logf("Source 1 (e.g., Popular Patterns):")
	for i, url := range urls1 {
		t.Logf("  [%d] %s", i+1, url)
	}

	t.Logf("\nSource 2 (e.g., Model Patterns):")
	for i, url := range urls2 {
		t.Logf("  [%d] %s", i+1, url)
	}

	// Симуляция текущей дедупликации (простое сравнение строк)
	urlMap := make(map[string]bool)
	var combined []string

	for _, url := range urls1 {
		if !urlMap[url] {
			combined = append(combined, url)
			urlMap[url] = true
		}
	}

	detectedDuplicates := 0
	for _, url := range urls2 {
		if !urlMap[url] {
			combined = append(combined, url)
			urlMap[url] = true
		} else {
			detectedDuplicates++
		}
	}

	t.Logf("\nCurrent deduplication results:")
	t.Logf("  Source 1 URLs: %d", len(urls1))
	t.Logf("  Source 2 URLs: %d", len(urls2))
	t.Logf("  Combined URLs: %d", len(combined))
	t.Logf("  Duplicates detected by string comparison: %d", detectedDuplicates)

	// Канонический анализ
	canonicalMap := make(map[string][]string)
	for _, url := range combined {
		canonical := makeCanonical(url)
		canonicalMap[canonical] = append(canonicalMap[canonical], url)
	}

	realUnique := len(canonicalMap)
	semanticDuplicates := len(combined) - realUnique

	t.Logf("\nCanonical URL analysis:")
	t.Logf("  Real unique streams: %d", realUnique)
	t.Logf("  Semantic duplicates: %d", semanticDuplicates)
	t.Logf("  Current dedup effectiveness: %.1f%%",
		float64(detectedDuplicates)/float64(len(urls1)+len(urls2))*100)
	t.Logf("  Should be dedup effectiveness: %.1f%%",
		float64(semanticDuplicates+detectedDuplicates)/float64(len(urls1)+len(urls2))*100)

	if semanticDuplicates > 0 {
		t.Logf("\n⚠️  PROBLEM: %d semantic duplicates NOT detected", semanticDuplicates)
	}
}

// TestWorstCaseScenario показывает худший сценарий
func TestWorstCaseScenario(t *testing.T) {
	logger := &mockLogger{}
	builder := NewBuilder([]string{}, logger)

	// Паттерн, который есть везде: Popular + Model + ONVIF
	entry := models.CameraEntry{
		Type:     "JPEG",
		Protocol: "http",
		Port:     80,
		URL:      "snapshot.jpg",
	}

	ctx := BuildContext{
		IP:       "192.168.1.100",
		Username: "admin",
		Password: "12345",
		Port:     80,
	}

	// Симуляция 3 источников
	popularURLs := builder.BuildURLsFromEntry(entry, ctx)
	modelURLs := builder.BuildURLsFromEntry(entry, ctx)

	// ONVIF может вернуть URL без credentials
	onvifURL := "http://192.168.1.100/snapshot.jpg"

	t.Logf("\n=== WORST CASE: Same pattern from 3 sources ===")
	t.Logf("Popular patterns generates: %d URLs", len(popularURLs))
	t.Logf("Model patterns generates: %d URLs", len(modelURLs))
	t.Logf("ONVIF returns: 1 URL")

	// Текущая дедупликация
	urlMap := make(map[string]bool)
	var all []string

	add := func(url string) {
		if !urlMap[url] {
			all = append(all, url)
			urlMap[url] = true
		}
	}

	for _, url := range popularURLs {
		add(url)
	}
	for _, url := range modelURLs {
		add(url)
	}
	add(onvifURL)

	t.Logf("\nAfter current deduplication:")
	t.Logf("  Total URLs to test: %d", len(all))

	for i, url := range all {
		t.Logf("  [%d] %s", i+1, url)
	}

	// Канонический анализ
	canonicalMap := make(map[string][]string)
	for _, url := range all {
		canonical := makeCanonical(url)
		canonicalMap[canonical] = append(canonicalMap[canonical], url)
	}

	t.Logf("\nCanonical analysis:")
	t.Logf("  Real unique streams: %d", len(canonicalMap))
	t.Logf("  URLs being tested: %d", len(all))
	t.Logf("  Waste: %d unnecessary tests (%.1f%%)",
		len(all)-len(canonicalMap),
		float64(len(all)-len(canonicalMap))/float64(len(all))*100)

	if len(all) > 1 {
		t.Logf("\n⚠️  CRITICAL: Testing the same stream %d times!", len(all))
		t.Logf("Expected time waste: ~%d seconds (assuming 2s per test)", (len(all)-1)*2)
	}
}

// makeCanonical - упрощенная нормализация URL для теста
func makeCanonical(rawURL string) string {
	url := rawURL

	// 1. Убрать credentials (user:pass@)
	if idx := strings.Index(url, "://"); idx >= 0 {
		protocol := url[:idx+3]
		rest := url[idx+3:]

		if atIdx := strings.Index(rest, "@"); atIdx >= 0 {
			rest = rest[atIdx+1:]
		}

		url = protocol + rest
	}

	// 2. Убрать auth query параметры
	authParams := []string{
		"user=", "username=", "usr=",
		"pwd=", "password=", "pass=",
	}

	for _, param := range authParams {
		if idx := strings.Index(url, "?"+param); idx >= 0 {
			// Найти конец параметра
			endIdx := strings.Index(url[idx+1:], "&")
			if endIdx >= 0 {
				url = url[:idx+1] + url[idx+1+endIdx+1:]
			} else {
				url = url[:idx]
			}
		}

		if idx := strings.Index(url, "&"+param); idx >= 0 {
			endIdx := strings.Index(url[idx+1:], "&")
			if endIdx >= 0 {
				url = url[:idx] + url[idx+1+endIdx:]
			} else {
				url = url[:idx]
			}
		}
	}

	// 3. Убрать trailing ?
	url = strings.TrimSuffix(url, "?")

	return url
}
