package promconfig

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

	"github.com/tidbcloud/metrics-integration/global/internal/infrastructure/regionalexecutor"
)

func RemoteAddMetricsKey(ctx context.Context, cluster_id, hashed_metrics_key, clusterConfig, executorURL string) error {
	requestURL, err := regionalexecutor.BuildURL(executorURL, "/api/v1/metrics-key/create")
	if err != nil {
		return err
	}
	// Wrap the package JSON inside {"helm_config": ""}
	requestPayload := map[string]string{
		"hashed_metrics_key": hashed_metrics_key,
		"cluster_id":         cluster_id,
		"cluster_config_map": clusterConfig,
	}

	requestBody, err := json.Marshal(requestPayload)
	if err != nil {
		return fmt.Errorf("failed to marshal request payload: %w", err)
	}

	httpClient := &http.Client{
		Timeout: 5 * time.Minute,
	}

	req, err := http.NewRequestWithContext(ctx, "POST", requestURL, bytes.NewBuffer(requestBody))
	if err != nil {
		return fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")

	resp, err := httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("failed to send request: %w", err)
	}
	defer closeResponseBody(resp.Body)

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read response: %w", err)
	}

	// Check if status code is not 200
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("remote apply failed with status %d: %s", resp.StatusCode, string(responseBody))
	}

	return nil
}

func RemoteDeleteMetricsKey(ctx context.Context, cluster_id, hashed_metrics_key, executorURL string) error {
	requestURL, err := regionalexecutor.BuildURL(executorURL, "/api/v1/metrics-key/delete")
	if err != nil {
		return err
	}
	// Wrap the package JSON inside {"helm_config": ""}
	requestPayload := map[string]string{
		"hashed_metrics_key": hashed_metrics_key,
		"cluster_id":         cluster_id,
	}

	requestBody, err := json.Marshal(requestPayload)
	if err != nil {
		return fmt.Errorf("failed to marshal request payload: %w", err)
	}

	httpClient := &http.Client{
		Timeout: 5 * time.Minute,
	}

	req, err := http.NewRequestWithContext(ctx, "POST", requestURL, bytes.NewBuffer(requestBody))
	if err != nil {
		return fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")

	resp, err := httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("failed to send request: %w", err)
	}
	defer closeResponseBody(resp.Body)

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read response: %w", err)
	}

	// Check if status code is not 200
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("remote apply failed with status %d: %s", resp.StatusCode, string(responseBody))
	}

	return nil
}

func RemoteScale(ctx context.Context, cluster_id, clusterConfig, executorURL string) error {
	requestURL, err := regionalexecutor.BuildURL(executorURL, "/api/v1/metrics-key/scale")
	if err != nil {
		return err
	}
	// Wrap the package JSON inside {"helm_config": ""}
	requestPayload := map[string]string{
		"cluster_id":         cluster_id,
		"cluster_config_map": clusterConfig,
	}

	requestBody, err := json.Marshal(requestPayload)
	if err != nil {
		return fmt.Errorf("failed to marshal request payload: %w", err)
	}

	httpClient := &http.Client{
		Timeout: 5 * time.Minute,
	}

	req, err := http.NewRequestWithContext(ctx, "POST", requestURL, bytes.NewBuffer(requestBody))
	if err != nil {
		return fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")

	resp, err := httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("failed to send request: %w", err)
	}
	defer closeResponseBody(resp.Body)

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read response: %w", err)
	}

	// Check if status code is not 200
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("remote apply failed with status %d: %s", resp.StatusCode, string(responseBody))
	}

	return nil
}

func RemoteClusterDelete(ctx context.Context, cluster_id, clusterConfig, executorURL string) error {
	requestURL, err := regionalexecutor.BuildURL(executorURL, "/api/v1/metrics-key/cluster-delete")
	if err != nil {
		return err
	}
	// Wrap the package JSON inside {"helm_config": ""}
	requestPayload := map[string]string{
		"cluster_id":         cluster_id,
		"cluster_config_map": clusterConfig,
	}

	requestBody, err := json.Marshal(requestPayload)
	if err != nil {
		return fmt.Errorf("failed to marshal request payload: %w", err)
	}

	httpClient := &http.Client{
		Timeout: 5 * time.Minute,
	}

	req, err := http.NewRequestWithContext(ctx, "POST", requestURL, bytes.NewBuffer(requestBody))
	if err != nil {
		return fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")

	resp, err := httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("failed to send request: %w", err)
	}
	defer closeResponseBody(resp.Body)

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read response: %w", err)
	}

	// Check if status code is not 200
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("remote apply failed with status %d: %s", resp.StatusCode, string(responseBody))
	}

	return nil
}

func closeResponseBody(body io.Closer) {
	if body == nil {
		return
	}
	_ = body.Close()
}
