// Copyright 2025 The Go MCP SDK Authors. All rights reserved.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package mcp_test

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/modelcontextprotocol/go-sdk/mcp"
)

// !+streamablehandler

// TODO: Until we have a way to clean up abandoned sessions, this test will leak goroutines (see #499)
func ExampleStreamableHTTPHandler() {
	// Create a new streamable handler, using the same MCP server for every request.
	//
	// Here, we configure it to serves application/json responses rather than
	// text/event-stream, just so the output below doesn't use random event ids.
	server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.1.0"}, nil)
	handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server {
		return server
	}, &mcp.StreamableHTTPOptions{JSONResponse: true})
	httpServer := httptest.NewServer(handler)
	defer httpServer.Close()

	// The SDK is currently permissive of some missing keys in "params".
	resp := mustPostMessage(`{"jsonrpc": "2.0", "id": 1, "method":"initialize", "params": {}}`, httpServer.URL)
	fmt.Println(resp)
	// Output:
	// {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"logging":{}},"protocolVersion":"2025-06-18","serverInfo":{"name":"server","version":"v0.1.0"}}}
}

// !-streamablehandler

// !+httpmiddleware

func ExampleStreamableHTTPHandler_middleware() {
	server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.1.0"}, nil)
	handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server {
		return server
	}, &mcp.StreamableHTTPOptions{Stateless: true})
	loggingHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		// Example debugging; you could also capture the response.
		body, err := io.ReadAll(req.Body)
		if err != nil {
			log.Fatal(err)
		}
		req.Body.Close() // ignore error
		req.Body = io.NopCloser(bytes.NewBuffer(body))
		fmt.Println(req.Method, string(body))
		handler.ServeHTTP(w, req)
	})
	httpServer := httptest.NewServer(loggingHandler)
	defer httpServer.Close()

	// The SDK is currently permissive of some missing keys in "params".
	mustPostMessage(`{"jsonrpc": "2.0", "id": 1, "method":"initialize", "params": {}}`, httpServer.URL)
	// Output:
	// POST {"jsonrpc": "2.0", "id": 1, "method":"initialize", "params": {}}
}

// !-httpmiddleware

func mustPostMessage(msg, url string) string {
	req := orFatal(http.NewRequest("POST", url, strings.NewReader(msg)))
	req.Header["Content-Type"] = []string{"application/json"}
	req.Header["Accept"] = []string{"application/json", "text/event-stream"}
	resp := orFatal(http.DefaultClient.Do(req))
	defer resp.Body.Close()
	body := orFatal(io.ReadAll(resp.Body))
	return string(body)
}

func orFatal[T any](t T, err error) T {
	if err != nil {
		log.Fatal(err)
	}
	return t
}
