package grpcclient

import (
	"context"
	"strings"
	"testing"
	"time"

	"google.golang.org/grpc"
)

func TestNormalizeRestoresTransportDefaults(t *testing.T) {
	cfg := Normalize(Config{})

	if cfg.DefaultTimeout != 5*time.Second || cfg.ConnectTimeout != 2*time.Second {
		t.Fatalf("deadline defaults mismatch: %+v", cfg)
	}
	if cfg.KeepaliveTime != 30*time.Second || cfg.KeepaliveTimeout != 10*time.Second {
		t.Fatalf("keepalive defaults mismatch: %+v", cfg)
	}
	if cfg.RetryMaxAttempts != 2 || cfg.RetryInitialBackoff != 100*time.Millisecond || cfg.RetryMaxBackoff != 500*time.Millisecond {
		t.Fatalf("retry defaults mismatch: %+v", cfg)
	}
}

func TestTimeoutInterceptorPreservesExistingDeadline(t *testing.T) {
	parent, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()
	before, _ := parent.Deadline()

	interceptor := timeoutUnaryInterceptor(time.Millisecond)
	err := interceptor(parent, "/svc/Method", nil, nil, nil, func(ctx context.Context, method string, req any, reply any, conn *grpc.ClientConn, opts ...grpc.CallOption) error {
		after, ok := ctx.Deadline()
		if !ok || !after.Equal(before) {
			t.Fatalf("deadline should be preserved: ok=%t before=%s after=%s", ok, before, after)
		}
		return nil
	})
	if err != nil {
		t.Fatalf("interceptor returned error: %v", err)
	}
}

func TestDefaultServiceConfigIncludesUnavailableRetry(t *testing.T) {
	serviceConfig := defaultServiceConfig(DefaultConfig())
	if !strings.Contains(serviceConfig, `"retryableStatusCodes":["UNAVAILABLE"]`) {
		t.Fatalf("retry policy missing UNAVAILABLE: %s", serviceConfig)
	}
	if !strings.Contains(serviceConfig, `"waitForReady":true`) {
		t.Fatalf("service config should enable waitForReady: %s", serviceConfig)
	}
}
