package pipeline

import (
	"bytes"
	"context"
	"errors"
	"net/http"
	"time"

	"github.com/grafana/grafana-plugin-sdk-go/data"
	"github.com/grafana/grafana/pkg/services/live/remotewrite"
)

type RemoteWriteConfig struct {
	// Endpoint to send streaming frames to.
	Endpoint string `json:"endpoint"`
	// User is a user for remote write request.
	User string `json:"user"`
	// Password for remote write endpoint.
	Password string `json:"password"`
}

type RemoteWriteOutput struct {
	config     RemoteWriteConfig
	httpClient *http.Client
}

func NewRemoteWriteOutput(config RemoteWriteConfig) *RemoteWriteOutput {
	return &RemoteWriteOutput{
		config:     config,
		httpClient: &http.Client{Timeout: 2 * time.Second},
	}
}

func (r RemoteWriteOutput) Output(_ context.Context, _ OutputVars, frame *data.Frame) ([]*ChannelFrame, error) {
	if r.config.Endpoint == "" {
		logger.Debug("Skip sending to remote write: no url")
		return nil, nil
	}

	// Use remote write for a stream.
	remoteWriteData, err := remotewrite.SerializeLabelsColumn(frame)
	if err != nil {
		logger.Error("Error serializing to remote write format", "error", err)
		return nil, err
	}

	logger.Debug("Sending to remote write endpoint", "url", r.config.Endpoint, "bodyLength", len(remoteWriteData))
	req, err := http.NewRequest(http.MethodPost, r.config.Endpoint, bytes.NewReader(remoteWriteData))
	if err != nil {
		logger.Error("Error constructing remote write request", "error", err)
		return nil, err
	}
	req.Header.Set("Content-Type", "application/x-protobuf")
	req.Header.Set("Content-Encoding", "snappy")
	req.Header.Set("X-Prometheus-Remote-Write-Version", "0.1.0")
	req.SetBasicAuth(r.config.User, r.config.Password)

	started := time.Now()
	resp, err := r.httpClient.Do(req)
	if err != nil {
		logger.Error("Error sending remote write request", "error", err)
		return nil, err
	}
	_ = resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		logger.Error("Unexpected response code from remote write endpoint", "code", resp.StatusCode)
		return nil, errors.New("unexpected response code from remote write endpoint")
	}
	logger.Debug("Successfully sent to remote write endpoint", "url", r.config.Endpoint, "elapsed", time.Since(started))
	return nil, nil
}
