package mutil

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

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.uber.org/zap"
)

func TestGetOptionalBoolParam(t *testing.T) {
	logger := zap.NewNop()

	tests := []struct {
		name     string
		query    string
		expected *bool
		hasError bool
	}{
		{
			name:     "valid true",
			query:    "?param=true",
			expected: boolPtr(true),
			hasError: false,
		},
		{
			name:     "valid false",
			query:    "?param=false",
			expected: boolPtr(false),
			hasError: false,
		},
		{
			name:     "missing parameter",
			query:    "?other=value",
			expected: nil,
			hasError: false,
		},
		{
			name:     "invalid value",
			query:    "?param=invalid",
			expected: nil,
			hasError: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			req, err := http.NewRequestWithContext(context.Background(), "GET", "http://example.com"+tt.query, nil)
			require.NoError(t, err)

			result, err := GetOptionalBoolParam(logger, req, "param")

			if tt.hasError {
				assert.Error(t, err)
			} else {
				assert.NoError(t, err)
			}

			if tt.expected == nil {
				assert.Nil(t, result)
			} else {
				assert.NotNil(t, result)
				assert.Equal(t, *tt.expected, *result)
			}
		})
	}
}

func TestGetOptionalInt64Param(t *testing.T) {
	logger := zap.NewNop()

	tests := []struct {
		name     string
		query    string
		expected *int64
		hasError bool
	}{
		{
			name:     "valid positive number",
			query:    "?param=123",
			expected: int64Ptr(123),
			hasError: false,
		},
		{
			name:     "valid negative number",
			query:    "?param=-456",
			expected: int64Ptr(-456),
			hasError: false,
		},
		{
			name:     "valid zero",
			query:    "?param=0",
			expected: int64Ptr(0),
			hasError: false,
		},
		{
			name:     "missing parameter",
			query:    "?other=value",
			expected: nil,
			hasError: false,
		},
		{
			name:     "invalid value",
			query:    "?param=invalid",
			expected: nil,
			hasError: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			req, err := http.NewRequestWithContext(context.Background(), "GET", "http://example.com"+tt.query, nil)
			require.NoError(t, err)

			result, err := GetOptionalInt64Param(logger, req, "param")

			if tt.hasError {
				assert.Error(t, err)
			} else {
				assert.NoError(t, err)
			}

			if tt.expected == nil {
				assert.Nil(t, result)
			} else {
				assert.NotNil(t, result)
				assert.Equal(t, *tt.expected, *result)
			}
		})
	}
}

// Helper functions for creating pointers to values
func boolPtr(b bool) *bool {
	return &b
}

func int64Ptr(i int64) *int64 {
	return &i
}
