package slowlog_explorer

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

// DataProxyRequest is the request body for the Data Proxy query endpoint.
type DataProxyRequest struct {
	SQL       string           `json:"sql"`
	ClusterID string           `json:"clusterId"`
	Timeout   int              `json:"timeout"`
	Options   DataProxyOptions `json:"options,omitempty"`
}

type DataProxyOptions struct {
	Vendor              string `json:"vendor,omitempty"`
	SkipSQLRewrite      bool   `json:"skipSQLRewrite,omitempty"`
	SkipTableManagement bool   `json:"skipTableManagement,omitempty"`
}

// DataProxyResponse is the response from the Data Proxy.
type DataProxyResponse struct {
	Columns  []string               `json:"columns"`
	Rows     [][]interface{}        `json:"rows"`
	Metadata map[string]interface{} `json:"metadata"`
}

// queryDataProxy sends a SQL query to the Clinic Data Proxy service.
func (s *Service) queryDataProxy(ctx context.Context, clusterID, sql string, timeout int, options ...DataProxyOptions) (*DataProxyResponse, error) {
	if timeout <= 0 {
		timeout = 60
	}

	var queryOptions DataProxyOptions
	if len(options) > 0 {
		queryOptions = options[0]
	}

	reqBody := DataProxyRequest{
		SQL:       sql,
		ClusterID: clusterID,
		Timeout:   timeout,
		Options:   queryOptions,
	}
	body, err := json.Marshal(reqBody)
	if err != nil {
		return nil, fmt.Errorf("marshal request: %w", err)
	}

	url := fmt.Sprintf("%s/data-proxy/query", s.DataProxyAddr)
	httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))
	if err != nil {
		return nil, fmt.Errorf("create request: %w", err)
	}
	httpReq.Header.Set("Content-Type", "application/json")
	if s.DataProxyToken != "" {
		httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.DataProxyToken))
	}

	client := &http.Client{Timeout: time.Duration(timeout+10) * time.Second}
	resp, err := client.Do(httpReq)
	if err != nil {
		return nil, fmt.Errorf("data proxy request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		respBody, _ := io.ReadAll(io.LimitReader(resp.Body, 500))
		return nil, fmt.Errorf("data proxy error %d: %s", resp.StatusCode, string(respBody))
	}

	var result DataProxyResponse
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("decode response: %w", err)
	}
	return &result, nil
}
