package web

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"gitgud.io/mike/mpv-manager/pkg/config"
	"gitgud.io/mike/mpv-manager/pkg/installer"
	"gitgud.io/mike/mpv-manager/pkg/platform"
	"gitgud.io/mike/mpv-manager/pkg/version"
)

// TestConvertClientUpdates_Filtering verifies that convertClientUpdates properly
// filters out apps that don't have updates available
func TestConvertClientUpdates_Filtering(t *testing.T) {
	// Create test server
	p := platform.Detect()
	cfg, _ := config.Load()
	releaseInfo := installer.ReleaseInfo{
		MpvVersion: "0.41.0",
		MPCQT: struct {
			X8664      struct{ URL, BLAKE3 string } `json:"x86-64"`
			AppVersion string                       `json:"app_version"`
		}{AppVersion: "22.2.0"},
		IINA: struct {
			ARM        struct{ URL, BLAKE3 string } `json:"arm"`
			Intel      struct{ URL, BLAKE3 string } `json:"intel"`
			AppVersion string                       `json:"app_version"`
		}{AppVersion: "1.3.2"},
	}
	inst := installer.NewInstaller(releaseInfo, config.GetInstallPath())

	server := NewServer(p, cfg, inst, &releaseInfo)

	// Test case 1: Updates with available updates (should be included)
	updatesWithUpdate := []version.UpdateItem{
		{
			MethodID:         "mpv-binary",
			AppName:          "MPV",
			CurrentVersion:   "0.40.0",
			AvailableVersion: "0.41.0",
			UpdateType:       "update",
		},
	}

	result := server.convertClientUpdates(updatesWithUpdate)
	if len(result) != 1 {
		t.Errorf("Expected 1 update, got %d", len(result))
	}
	if !result[0].UpdateAvailable {
		t.Errorf("Expected UpdateAvailable=true for update item")
	}

	// Test case 2: Updates without available updates (should be excluded)
	updatesWithoutUpdate := []version.UpdateItem{
		{
			MethodID:         "mpv-binary",
			AppName:          "MPV",
			CurrentVersion:   "0.41.0",
			AvailableVersion: "0.41.0",
			UpdateType:       "package-info", // Not an actual update
		},
	}

	result = server.convertClientUpdates(updatesWithoutUpdate)
	if len(result) != 0 {
		t.Errorf("Expected 0 updates (should filter out non-updates), got %d", len(result))
	}

	// Test case 3: Mixed updates (some with, some without)
	updatesMixed := []version.UpdateItem{
		{
			MethodID:         "mpv-binary",
			AppName:          "MPV",
			CurrentVersion:   "0.40.0",
			AvailableVersion: "0.41.0",
			UpdateType:       "update", // Should be included
		},
		{
			MethodID:         "iina",
			AppName:          "IINA",
			CurrentVersion:   "1.3.2",
			AvailableVersion: "1.3.2",
			UpdateType:       "package-info", // Should be excluded
		},
	}

	result = server.convertClientUpdates(updatesMixed)
	if len(result) != 1 {
		t.Errorf("Expected 1 update (1 included, 1 excluded), got %d", len(result))
	}
	if result[0].AppName != "MPV" {
		t.Errorf("Expected MPV to be included, got %s", result[0].AppName)
	}
}

// TestHandleCheckAppUpdatesAPI_Template verifies that the API returns
// the correct template with the correct data structure
func TestHandleCheckAppUpdatesAPI_Template(t *testing.T) {
	// Create test server
	p := platform.Detect()
	cfg, _ := config.Load()
	releaseInfo := installer.ReleaseInfo{
		MpvVersion: "0.41.0",
		MPCQT: struct {
			X8664      struct{ URL, BLAKE3 string } `json:"x86-64"`
			AppVersion string                       `json:"app_version"`
		}{AppVersion: "22.2.0"},
		IINA: struct {
			ARM        struct{ URL, BLAKE3 string } `json:"arm"`
			Intel      struct{ URL, BLAKE3 string } `json:"intel"`
			AppVersion string                       `json:"app_version"`
		}{AppVersion: "1.3.2"},
	}
	inst := installer.NewInstaller(releaseInfo, config.GetInstallPath())

	server := NewServer(p, cfg, inst, &releaseInfo)

	// Create request and recorder
	req := httptest.NewRequest("POST", "/api/apps/check-updates", nil)
	w := httptest.NewRecorder()

	// Call handler
	server.handleCheckAppUpdatesAPI(w, req)

	// Check status code
	if w.Code != http.StatusOK {
		t.Errorf("Expected status %d, got %d", http.StatusOK, w.Code)
	}

	// Check content type
	contentType := w.Header().Get("Content-Type")
	if contentType != "text/html" {
		t.Errorf("Expected content type 'text/html', got %q", contentType)
	}

	// Check that response contains the client-updates template output
	body := w.Body.String()

	// If there are no updates, should show "No Updates Available"
	if strings.Contains(body, "No Updates Available") {
		// This is expected when no updates are available
		// Just verify the template is being rendered
		return
	}

	// If there are updates, should contain app cards
	// The important thing is that it's rendering the correct template
	// (client-updates, not installed-apps-list)
	if !strings.Contains(body, "No Updates Available") && !strings.Contains(body, "Install Update") {
		t.Errorf("Expected response to contain either 'No Updates Available' or 'Install Update', got: %s", body)
	}
}
