package toolsdemo

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

	"connectrpc.com/connect"
	"github.com/go-playground/validator/v10"
	"google.golang.org/protobuf/types/known/wrapperspb"
)

func Example_validatorNames() {
	v := validator.New(validator.WithRequiredStructEnabled())
	for _, s := range []string{"123", "-12", "+12", "1.2", "abc"} {
		fmt.Printf("%s numeric=%v number=%v\n", s, v.Var(s, "required,numeric,len=3") == nil, v.Var(s, "required,number,len=3") == nil)
	}
	// Output:
	// 123 numeric=true number=true
	// -12 numeric=true number=false
	// +12 numeric=true number=false
	// 1.2 numeric=true number=false
	// abc numeric=false number=false
}
func TestConnectAndGRPCOnHTTP(t *testing.T) {
	const path = "/demo.v1.Greeter/Hello"
	h := connect.NewUnaryHandler(path, func(ctx context.Context, r *connect.Request[wrapperspb.StringValue]) (*connect.Response[wrapperspb.StringValue], error) {
		if r.Msg.Value == "" {
			return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("name required"))
		}
		return connect.NewResponse(wrapperspb.String("hello " + r.Msg.Value)), nil
	})
	mux := http.NewServeMux()
	mux.Handle(path, h)
	server := httptest.NewUnstartedServer(mux)
	server.EnableHTTP2 = true
	server.StartTLS()
	defer server.Close()
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()
	for _, mode := range []struct {
		name    string
		options []connect.ClientOption
	}{{"Connect", nil}, {"gRPC", []connect.ClientOption{connect.WithGRPC()}}, {"gRPC-Web", []connect.ClientOption{connect.WithGRPCWeb()}}} {
		c := connect.NewClient[wrapperspb.StringValue, wrapperspb.StringValue](server.Client(), server.URL+path, mode.options...)
		result, err := c.CallUnary(ctx, connect.NewRequest(wrapperspb.String("Go")))
		if err != nil || result.Msg.Value != "hello Go" {
			t.Fatalf("%s %v %v", mode.name, result, err)
		}
		_, err = c.CallUnary(ctx, connect.NewRequest(wrapperspb.String("")))
		if connect.CodeOf(err) != connect.CodeInvalidArgument {
			t.Fatal(err)
		}
		t.Logf("%s: %s; empty name=%s", mode.name, result.Msg.Value, connect.CodeOf(err))
	}
}
func TestGeneratedModelDoesNotValidatePattern(t *testing.T) {
	u := User{Id: "bad-value"}
	b, err := json.Marshal(u)
	if err != nil {
		t.Fatal(err)
	}
	if string(b) != `{"id":"bad-value"}` {
		t.Fatal(string(b))
	}
	t.Log("generated model accepts:", string(b))
}
