package watch_aggregator //nolint:staticcheck

import (
	"context"
	"fmt"
	"io"
	"net/http"

	"github.com/coder/websocket"
)

const (
	acceptedSubprotocolName = "gitlab-agent-watch-api"
)

var (
	_ WebSocketInterface = (*websocket.Conn)(nil)
)

type WebSocketAcceptFunc func() (WebSocketInterface, error)

func WebSocketAccept(w http.ResponseWriter, r *http.Request) (WebSocketInterface, error) {
	c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
		Subprotocols: []string{acceptedSubprotocolName},
		// InsecureSkipVerify is used to disable the Origin check.
		// We enable it because:
		// - (1) we already do the Origin check in the proxy.
		// - (2) the websocket package doesn't implement it correctly:
		//       see https://github.com/coder/websocket/issues/529
		InsecureSkipVerify: true,
	})
	if err != nil {
		return nil, err
	}

	if c.Subprotocol() == "" {
		err = fmt.Errorf("protocol unspecified, please use the %q protocol", acceptedSubprotocolName)
		_ = c.Close(websocket.StatusProtocolError, err.Error())
		return nil, err
	}
	return c, nil
}

// WebSocketInterface is used to interface with the websocket package.
// The purpose of this is NOT to hide the websocket package (as types of it are exposed),
// but to make the Watch Aggregator easily testable.
type WebSocketInterface interface {
	Reader(ctx context.Context) (websocket.MessageType, io.Reader, error)
	Writer(ctx context.Context, typ websocket.MessageType) (io.WriteCloser, error)
	Close(statusCode websocket.StatusCode, reason string) error
}
