package rtcclient_test

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/qy/hw-ws-service/internal/rtcclient"
)

func successBody(title, audioURL string) []byte {
	b, _ := json.Marshal(map[string]any{
		"code":    0,
		"message": "success",
		"data": map[string]string{
			"title":     title,
			"audio_url": audioURL,
		},
	})
	return b
}

func errorBody(code int, msg string) []byte {
	b, _ := json.Marshal(map[string]any{
		"code":    code,
		"message": msg,
		"data":    nil,
	})
	return b
}

func TestFetchStoryByMAC_Success(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/api/v1/devices/stories/" {
			t.Errorf("unexpected path: %s", r.URL.Path)
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(successBody("小红帽", "https://example.com/story.mp3"))
	}))
	defer srv.Close()

	client := rtcclient.New(srv.URL)
	story, err := client.FetchStoryByMAC(context.Background(), "aa:bb:cc:dd:ee:ff")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if story == nil {
		t.Fatal("expected story, got nil")
	}
	if story.Title != "小红帽" {
		t.Errorf("title = %q, want %q", story.Title, "小红帽")
	}
	if story.AudioURL != "https://example.com/story.mp3" {
		t.Errorf("audio_url = %q", story.AudioURL)
	}
}

// TestFetchStoryByMAC_MACUppercase verifies the client always sends uppercase MAC.
func TestFetchStoryByMAC_MACUppercase(t *testing.T) {
	var gotMAC string
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		gotMAC = r.URL.Query().Get("mac_address")
		w.Header().Set("Content-Type", "application/json")
		w.Write(successBody("test", "https://example.com/t.mp3"))
	}))
	defer srv.Close()

	client := rtcclient.New(srv.URL)
	client.FetchStoryByMAC(context.Background(), "aa:bb:cc:dd:ee:ff") //nolint:errcheck
	if gotMAC != "AA:BB:CC:DD:EE:FF" {
		t.Errorf("MAC not uppercased: got %q, want %q", gotMAC, "AA:BB:CC:DD:EE:FF")
	}
}

// TestFetchStoryByMAC_NotFound verifies that HTTP 404 returns (nil, nil).
func TestFetchStoryByMAC_NotFound(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusNotFound)
	}))
	defer srv.Close()

	client := rtcclient.New(srv.URL)
	story, err := client.FetchStoryByMAC(context.Background(), "AA:BB:CC:DD:EE:FF")
	if err != nil {
		t.Fatalf("unexpected error for 404: %v", err)
	}
	if story != nil {
		t.Errorf("expected nil story for 404, got %+v", story)
	}
}

// TestFetchStoryByMAC_BusinessError verifies that code != 0 returns (nil, nil).
func TestFetchStoryByMAC_BusinessError(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.Write(errorBody(404, "暂无可播放的故事"))
	}))
	defer srv.Close()

	client := rtcclient.New(srv.URL)
	story, err := client.FetchStoryByMAC(context.Background(), "AA:BB:CC:DD:EE:FF")
	if err != nil {
		t.Fatalf("unexpected error for business error response: %v", err)
	}
	if story != nil {
		t.Errorf("expected nil story for business error, got %+v", story)
	}
}

// TestFetchStoryByMAC_ServerError verifies that HTTP 5xx returns an error.
func TestFetchStoryByMAC_ServerError(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusInternalServerError)
	}))
	defer srv.Close()

	client := rtcclient.New(srv.URL)
	_, err := client.FetchStoryByMAC(context.Background(), "AA:BB:CC:DD:EE:FF")
	if err == nil {
		t.Error("expected error for HTTP 500, got nil")
	}
}

// TestFetchStoryByMAC_ContextCanceled verifies that a canceled context returns an error.
func TestFetchStoryByMAC_ContextCanceled(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Never respond — let the client time out
		<-r.Context().Done()
	}))
	defer srv.Close()

	ctx, cancel := context.WithCancel(context.Background())
	cancel() // cancel immediately

	client := rtcclient.New(srv.URL)
	_, err := client.FetchStoryByMAC(ctx, "AA:BB:CC:DD:EE:FF")
	if err == nil {
		t.Error("expected error for canceled context, got nil")
	}
}
