package clientv2

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
)

type remoteQueryClient interface {
	// RegisterRemoteQuery notifies the manager that a query has been set to execute remotely.
	RegisterRemoteQuery(ctx context.Context, queryID, queryAddr string) error
}

var _ remoteQueryClient = &client{}

func (c *client) postWithContext(ctx context.Context, addr string, data []byte) (*http.Response, error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, addr, bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	return c.httpClient.Do(req)
}

func (c *client) RegisterRemoteQuery(ctx context.Context, queryID, queryAddr string) error {
	// TODO: Use grpc after server refactor.
	type Query struct {
		QueryID      string `json:"query_id"`
		TiDBPool     string `json:"tidb_pool"`
		KeyspaceName string `json:"keyspace_name"`
		QueryAddr    string `json:"query_addr"` // http://host:port/remote-query/{query-id}
	}

	query := Query{
		QueryID:      queryID,
		TiDBPool:     c.tidbPool,
		KeyspaceName: c.keyspaceName,
		QueryAddr:    queryAddr,
	}
	data, err := json.Marshal(query)
	if err != nil {
		return err
	}
	addr, err := url.JoinPath(c.scalerAddr, "scaler/api/v1/remote-query/query")
	if err != nil {
		return err
	}
	res, err := c.postWithContext(ctx, addr, data)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
		return fmt.Errorf("failed to register remote query: %s", res.Status)
	}
	return nil
}
