package vision

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"

	"github.com/photoprism/photoprism/pkg/clean"
	"github.com/photoprism/photoprism/pkg/media/http/header"
)

// PerformApiRequest performs a Vision API request and returns the result.
func PerformApiRequest(apiRequest *ApiRequest, uri, method, key string) (apiResponse *ApiResponse, err error) {
	if apiRequest == nil {
		return apiResponse, errors.New("api request is nil")
	}

	data, jsonErr := apiRequest.JSON()

	if jsonErr != nil {
		return apiResponse, jsonErr
	}

	// Create HTTP client and authenticated service API request.
	client := http.Client{Timeout: ServiceTimeout}
	req, reqErr := http.NewRequest(method, uri, bytes.NewReader(data))

	// Add "application/json" content type header.
	header.SetContentType(req, header.ContentTypeJson)

	// Add an authentication header if an access token is configured.
	if key != "" {
		header.SetAuthorization(req, key)
	}

	if reqErr != nil {
		return apiResponse, reqErr
	}

	// Perform API request.
	clientResp, clientErr := client.Do(req)

	if clientErr != nil {
		return apiResponse, clientErr
	}

	// Parse and return response, or an error if the request failed.
	switch apiRequest.GetResponseFormat() {
	case ApiFormatVision:
		apiResponse = &ApiResponse{}
		if apiJson, apiErr := io.ReadAll(clientResp.Body); apiErr != nil {
			return apiResponse, apiErr
		} else if apiErr = json.Unmarshal(apiJson, apiResponse); apiErr != nil {
			return apiResponse, apiErr
		} else if clientResp.StatusCode >= 300 {
			log.Debugf("vision: %s (status code %d)", apiJson, clientResp.StatusCode)
		}
	default:
		return apiResponse, fmt.Errorf("unsupported response format %s", clean.Log(apiRequest.responseFormat))
	}

	return apiResponse, nil
}
