/**
 * Go SDK for OpenFGA
 *
 * API version: 1.x
 * Website: https://openfga.dev
 * Documentation: https://openfga.dev/docs
 * Support: https://openfga.dev/community
 * License: [Apache-2.0](https://github.com/openfga/go-sdk/blob/main/LICENSE)
 *
 * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT.
 */

package client

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

	openfga "github.com/openfga/go-sdk"
)

func TestClientStreamedListObjects_Success(t *testing.T) {
	objects := []string{"document:1", "document:2", "document:3"}
	expectedResults := []string{}
	for _, obj := range objects {
		expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`)
	}
	responseBody := strings.Join(expectedResults, "\n")

	storeId := "01ARZ3NDEKTSV4RRFFQ69G5FAV"

	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expectedPath := "/stores/" + storeId + "/streamed-list-objects"
		if r.URL.Path != expectedPath {
			t.Errorf("Expected path %s, got %s", expectedPath, r.URL.Path)
		}

		w.Header().Set("Content-Type", "application/x-ndjson")
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte(responseBody))
	}))
	defer server.Close()

	config := ClientConfiguration{
		ApiUrl:  server.URL,
		StoreId: storeId,
	}

	client, err := NewSdkClient(&config)
	if err != nil {
		t.Fatalf("Failed to create client: %v", err)
	}

	ctx := context.Background()

	response, err := client.StreamedListObjects(ctx).
		Body(ClientStreamedListObjectsRequest{
			Type:     "document",
			Relation: "viewer",
			User:     "user:anne",
		}).
		Execute()

	if err != nil {
		t.Fatalf("StreamedListObjects failed: %v", err)
	}

	defer response.Close()

	receivedObjects := []string{}
	for obj := range response.Objects {
		receivedObjects = append(receivedObjects, obj.Object)
	}

	if err := <-response.Errors; err != nil {
		t.Fatalf("Received error from response: %v", err)
	}

	if len(receivedObjects) != len(objects) {
		t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects))
	}

	for i, expected := range objects {
		if receivedObjects[i] != expected {
			t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i])
		}
	}
}

func TestClientStreamedListObjects_WithOptions(t *testing.T) {
	authModelId := "01ARZ3NDEKTSV4RRFFQ69G5FAV"
	objects := []string{"document:1"}
	responseBody := `{"result":{"object":"document:1"}}`

	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/x-ndjson")
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte(responseBody))
	}))
	defer server.Close()

	config := ClientConfiguration{
		ApiUrl:  server.URL,
		StoreId: "01ARZ3NDEKTSV4RRFFQ69G5FAV",
	}

	client, err := NewSdkClient(&config)
	if err != nil {
		t.Fatalf("Failed to create client: %v", err)
	}

	ctx := context.Background()
	consistency := openfga.CONSISTENCYPREFERENCE_HIGHER_CONSISTENCY

	response, err := client.StreamedListObjects(ctx).
		Body(ClientStreamedListObjectsRequest{
			Type:     "document",
			Relation: "viewer",
			User:     "user:anne",
		}).
		Options(ClientStreamedListObjectsOptions{
			AuthorizationModelId: &authModelId,
			Consistency:          &consistency,
		}).
		Execute()

	if err != nil {
		t.Fatalf("StreamedListObjects with options failed: %v", err)
	}

	defer response.Close()

	receivedObjects := []string{}
	for obj := range response.Objects {
		receivedObjects = append(receivedObjects, obj.Object)
	}

	if len(receivedObjects) != len(objects) {
		t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects))
	}
}

func TestClientStreamedListObjects_ErrorHandling(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusInternalServerError)
		_, _ = w.Write([]byte(`{"code":"internal_error","message":"Internal server error"}`))
	}))
	defer server.Close()

	config := ClientConfiguration{
		ApiUrl:  server.URL,
		StoreId: "01ARZ3NDEKTSV4RRFFQ69G5FAV",
	}

	client, err := NewSdkClient(&config)
	if err != nil {
		t.Fatalf("Failed to create client: %v", err)
	}

	ctx := context.Background()

	_, err = client.StreamedListObjects(ctx).
		Body(ClientStreamedListObjectsRequest{
			Type:     "document",
			Relation: "viewer",
			User:     "user:anne",
		}).
		Execute()

	if err == nil {
		t.Fatal("Expected error from StreamedListObjects, got nil")
	}
}

func TestClientStreamedListObjects_NoStoreId(t *testing.T) {
	config := ClientConfiguration{
		ApiUrl: "http://localhost:8080",
	}

	client, err := NewSdkClient(&config)
	if err != nil {
		t.Fatalf("Failed to create client: %v", err)
	}

	ctx := context.Background()

	_, err = client.StreamedListObjects(ctx).
		Body(ClientStreamedListObjectsRequest{
			Type:     "document",
			Relation: "viewer",
			User:     "user:anne",
		}).
		Execute()

	if err == nil {
		t.Fatal("Expected error for missing store ID, got nil")
	}
}

func TestClientStreamedListObjects_CustomBufferSize(t *testing.T) {
	objects := []string{"document:1", "document:2", "document:3", "document:4", "document:5"}
	expectedResults := []string{}
	for _, obj := range objects {
		expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`)
	}
	responseBody := strings.Join(expectedResults, "\n")

	storeId := "01ARZ3NDEKTSV4RRFFQ69G5FAV"

	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/x-ndjson")
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte(responseBody))
	}))
	defer server.Close()

	config := ClientConfiguration{
		ApiUrl:  server.URL,
		StoreId: storeId,
	}

	client, err := NewSdkClient(&config)
	if err != nil {
		t.Fatalf("Failed to create client: %v", err)
	}

	ctx := context.Background()
	customBufferSize := 50

	response, err := client.StreamedListObjects(ctx).
		Body(ClientStreamedListObjectsRequest{
			Type:     "document",
			Relation: "viewer",
			User:     "user:anne",
		}).
		Options(ClientStreamedListObjectsOptions{
			StreamBufferSize: &customBufferSize,
		}).
		Execute()

	if err != nil {
		t.Fatalf("StreamedListObjects with custom buffer size failed: %v", err)
	}

	defer response.Close()

	receivedObjects := []string{}
	for obj := range response.Objects {
		receivedObjects = append(receivedObjects, obj.Object)
	}

	if err := <-response.Errors; err != nil {
		t.Fatalf("Received error from response: %v", err)
	}

	if len(receivedObjects) != len(objects) {
		t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects))
	}

	for i, expected := range objects {
		if receivedObjects[i] != expected {
			t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i])
		}
	}
}

func TestClientStreamedListObjects_DefaultBufferSize(t *testing.T) {
	objects := []string{"document:1", "document:2"}
	expectedResults := []string{}
	for _, obj := range objects {
		expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`)
	}
	responseBody := strings.Join(expectedResults, "\n")

	storeId := "01ARZ3NDEKTSV4RRFFQ69G5FAV"

	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/x-ndjson")
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte(responseBody))
	}))
	defer server.Close()

	config := ClientConfiguration{
		ApiUrl:  server.URL,
		StoreId: storeId,
	}

	client, err := NewSdkClient(&config)
	if err != nil {
		t.Fatalf("Failed to create client: %v", err)
	}

	ctx := context.Background()
	zeroBufferSize := 0

	response, err := client.StreamedListObjects(ctx).
		Body(ClientStreamedListObjectsRequest{
			Type:     "document",
			Relation: "viewer",
			User:     "user:anne",
		}).
		Options(ClientStreamedListObjectsOptions{
			StreamBufferSize: &zeroBufferSize,
		}).
		Execute()

	if err != nil {
		t.Fatalf("StreamedListObjects with default buffer size failed: %v", err)
	}

	defer response.Close()

	receivedObjects := []string{}
	for obj := range response.Objects {
		receivedObjects = append(receivedObjects, obj.Object)
	}

	if err := <-response.Errors; err != nil {
		t.Fatalf("Received error from response: %v", err)
	}

	if len(receivedObjects) != len(objects) {
		t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects))
	}
}
