package helm

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

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

func RemoteApply(ctx context.Context, p Package, executorURL string) error {
	requestURL, err := regionalexecutor.BuildURL(executorURL, "/api/v1/apply")
	if err != nil {
		return err
	}

	// Marshal the package into JSON
	packageJSON, err := json.Marshal(p)
	if err != nil {
		return fmt.Errorf("failed to marshal package: %w", err)
	}

	// Wrap the package JSON inside {"helm_config": ""}
	requestPayload := map[string]string{
		"helm_config": string(packageJSON),
	}

	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 func() {
		_ = resp.Body.Close()
	}()

	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 RemoteUninstall(ctx context.Context, p Package, executorURL string) error {
	requestURL, err := regionalexecutor.BuildURL(executorURL, "/api/v1/uninstall")
	if err != nil {
		return err
	}

	// Marshal the package into JSON
	packageJSON, err := json.Marshal(p)
	if err != nil {
		return fmt.Errorf("failed to marshal package: %w", err)
	}

	// Wrap the package JSON inside {"helm_config": ""}
	requestPayload := map[string]string{
		"helm_config": string(packageJSON),
	}

	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 func() {
		_ = resp.Body.Close()
	}()

	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
}
