// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Code generated by the Google Gen AI SDK generator DO NOT EDIT.

package genai

import (
	"context"
	"fmt"
	"net/http"
	"reflect"
	"strings"
)

func fetchPredictOperationParametersToVertex(fromObject map[string]any, parentObject map[string]any, rootObject map[string]any) (toObject map[string]any, err error) {
	toObject = make(map[string]any)

	fromOperationName := InternalGetValueByPath(fromObject, []string{"operationName"})
	if fromOperationName != nil {
		InternalSetValueByPath(toObject, []string{"operationName"}, fromOperationName)
	}

	fromResourceName := InternalGetValueByPath(fromObject, []string{"resourceName"})
	if fromResourceName != nil {
		InternalSetValueByPath(toObject, []string{"_url", "resourceName"}, fromResourceName)
	}

	return toObject, nil
}

func getOperationParametersToMldev(fromObject map[string]any, parentObject map[string]any, rootObject map[string]any) (toObject map[string]any, err error) {
	toObject = make(map[string]any)

	fromOperationName := InternalGetValueByPath(fromObject, []string{"operationName"})
	if fromOperationName != nil {
		InternalSetValueByPath(toObject, []string{"_url", "operationName"}, fromOperationName)
	}

	return toObject, nil
}

func getOperationParametersToVertex(fromObject map[string]any, parentObject map[string]any, rootObject map[string]any) (toObject map[string]any, err error) {
	toObject = make(map[string]any)

	fromOperationName := InternalGetValueByPath(fromObject, []string{"operationName"})
	if fromOperationName != nil {
		InternalSetValueByPath(toObject, []string{"_url", "operationName"}, fromOperationName)
	}

	return toObject, nil
}

func uploadToFileSearchStoreOperationFromMldev(fromObject map[string]any, parentObject map[string]any, rootObject map[string]any) (toObject map[string]any, err error) {
	toObject = make(map[string]any)

	fromName := InternalGetValueByPath(fromObject, []string{"name"})
	if fromName != nil {
		InternalSetValueByPath(toObject, []string{"name"}, fromName)
	}

	fromMetadata := InternalGetValueByPath(fromObject, []string{"metadata"})
	if fromMetadata != nil {
		InternalSetValueByPath(toObject, []string{"metadata"}, fromMetadata)
	}

	fromDone := InternalGetValueByPath(fromObject, []string{"done"})
	if fromDone != nil {
		InternalSetValueByPath(toObject, []string{"done"}, fromDone)
	}

	fromError := InternalGetValueByPath(fromObject, []string{"error"})
	if fromError != nil {
		InternalSetValueByPath(toObject, []string{"error"}, fromError)
	}

	fromResponse := InternalGetValueByPath(fromObject, []string{"response"})
	if fromResponse != nil {
		fromResponse, err = uploadToFileSearchStoreResponseFromMldev(fromResponse.(map[string]any), toObject, rootObject)
		if err != nil {
			return nil, err
		}

		InternalSetValueByPath(toObject, []string{"response"}, fromResponse)
	}

	return toObject, nil
}

func uploadToFileSearchStoreResponseFromMldev(fromObject map[string]any, parentObject map[string]any, rootObject map[string]any) (toObject map[string]any, err error) {
	toObject = make(map[string]any)

	fromSdkHttpResponse := InternalGetValueByPath(fromObject, []string{"sdkHttpResponse"})
	if fromSdkHttpResponse != nil {
		InternalSetValueByPath(toObject, []string{"sdkHttpResponse"}, fromSdkHttpResponse)
	}

	fromParent := InternalGetValueByPath(fromObject, []string{"parent"})
	if fromParent != nil {
		InternalSetValueByPath(toObject, []string{"parent"}, fromParent)
	}

	fromDocumentName := InternalGetValueByPath(fromObject, []string{"documentName"})
	if fromDocumentName != nil {
		InternalSetValueByPath(toObject, []string{"documentName"}, fromDocumentName)
	}

	return toObject, nil
}

// Operations provides methods for managing the long-running operations.
// You don't need to initiate this struct. Create a client instance via NewClient, and
// then access Operations through client.Operations field.
type Operations struct {
	apiClient *InternalAPIClient
}

func (m Operations) getVideosOperation(ctx context.Context, operationName string, config *GetOperationConfig) (*GenerateVideosOperation, error) {
	parameterMap := make(map[string]any)

	kwargs := map[string]any{"operationName": operationName, "config": config}
	InternalDeepMarshal(kwargs, &parameterMap)

	var httpOptions *HTTPOptions
	if config == nil || config.HTTPOptions == nil {
		httpOptions = &HTTPOptions{}
	} else {
		httpOptions = config.HTTPOptions
	}
	if httpOptions.Headers == nil {
		httpOptions.Headers = http.Header{}
	}
	var response = new(GenerateVideosOperation)
	var responseMap map[string]any
	var fromConverter func(map[string]any, map[string]any, map[string]any) (map[string]any, error)
	var toConverter func(map[string]any, map[string]any, map[string]any) (map[string]any, error)
	if m.apiClient.ClientConfig().Backend == BackendVertexAI {
		toConverter = getOperationParametersToVertex
		fromConverter = generateVideosOperationFromVertex
	} else {
		toConverter = getOperationParametersToMldev
		fromConverter = generateVideosOperationFromMldev
	}

	body, err := toConverter(parameterMap, nil, parameterMap)
	if err != nil {
		return nil, err
	}

	var path string
	var urlParams map[string]any
	if _, ok := body["_url"]; ok {
		urlParams = body["_url"].(map[string]any)
		delete(body, "_url")
	}
	path, err = InternalFormatMap("{operationName}", urlParams)
	if err != nil {
		return nil, fmt.Errorf("invalid url params: %#v.\n%w", urlParams, err)
	}
	if _, ok := body["_query"]; ok {
		query, err := InternalCreateURLQuery(body["_query"].(map[string]any))
		if err != nil {
			return nil, err
		}
		path += "?" + query
		delete(body, "_query")
	}
	responseMap, err = sendRequest(ctx, m.apiClient, path, http.MethodGet, body, httpOptions)
	if err != nil {
		return nil, err
	}
	if fromConverter != nil {
		responseMap, err = fromConverter(responseMap, nil, parameterMap)
	}
	if err != nil {
		return nil, err
	}
	err = InternalMapToStruct(responseMap, response)
	if err != nil {
		return nil, err
	}

	if field, ok := reflect.TypeOf(response).Elem().FieldByName("SDKHTTPResponse"); ok {
		{
			if reflect.ValueOf(response).Elem().FieldByName("SDKHTTPResponse").IsValid() {
				{
					reflect.ValueOf(response).Elem().FieldByName("SDKHTTPResponse").Set(reflect.Zero(field.Type))
				}
			}
		}
	}

	return response, nil
}

func (m Operations) fetchPredictVideosOperation(ctx context.Context, operationName string, resourceName string, config *FetchPredictOperationConfig) (*GenerateVideosOperation, error) {
	parameterMap := make(map[string]any)

	kwargs := map[string]any{"operationName": operationName, "resourceName": resourceName, "config": config}
	InternalDeepMarshal(kwargs, &parameterMap)

	var httpOptions *HTTPOptions
	if config == nil || config.HTTPOptions == nil {
		httpOptions = &HTTPOptions{}
	} else {
		httpOptions = config.HTTPOptions
	}
	if httpOptions.Headers == nil {
		httpOptions.Headers = http.Header{}
	}
	var response = new(GenerateVideosOperation)
	var responseMap map[string]any
	var fromConverter func(map[string]any, map[string]any, map[string]any) (map[string]any, error)
	var toConverter func(map[string]any, map[string]any, map[string]any) (map[string]any, error)
	if m.apiClient.ClientConfig().Backend == BackendVertexAI {
		toConverter = fetchPredictOperationParametersToVertex
		fromConverter = generateVideosOperationFromVertex
	} else {

		return nil, fmt.Errorf("method FetchPredictVideosOperation is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode. You can choose to use Gemini Enterprise Agent Platform by setting ClientConfig.Backend to BackendEnterprise.")

	}

	body, err := toConverter(parameterMap, nil, parameterMap)
	if err != nil {
		return nil, err
	}

	var path string
	var urlParams map[string]any
	if _, ok := body["_url"]; ok {
		urlParams = body["_url"].(map[string]any)
		delete(body, "_url")
	}
	if m.apiClient.ClientConfig().Backend == BackendVertexAI {
		path, err = InternalFormatMap("{resourceName}:fetchPredictOperation", urlParams)
	} else {
		path, err = InternalFormatMap("None", urlParams)
	}
	if err != nil {
		return nil, fmt.Errorf("invalid url params: %#v.\n%w", urlParams, err)
	}
	if _, ok := body["_query"]; ok {
		query, err := InternalCreateURLQuery(body["_query"].(map[string]any))
		if err != nil {
			return nil, err
		}
		path += "?" + query
		delete(body, "_query")
	}
	responseMap, err = sendRequest(ctx, m.apiClient, path, http.MethodPost, body, httpOptions)
	if err != nil {
		return nil, err
	}
	if fromConverter != nil {
		responseMap, err = fromConverter(responseMap, nil, parameterMap)
	}
	if err != nil {
		return nil, err
	}
	err = InternalMapToStruct(responseMap, response)
	if err != nil {
		return nil, err
	}

	if field, ok := reflect.TypeOf(response).Elem().FieldByName("SDKHTTPResponse"); ok {
		{
			if reflect.ValueOf(response).Elem().FieldByName("SDKHTTPResponse").IsValid() {
				{
					reflect.ValueOf(response).Elem().FieldByName("SDKHTTPResponse").Set(reflect.Zero(field.Type))
				}
			}
		}
	}

	return response, nil
}

func (m Operations) getUploadToFileSearchStoreOperation(ctx context.Context, operationName string, config *GetOperationConfig) (*UploadToFileSearchStoreOperation, error) {
	parameterMap := make(map[string]any)

	kwargs := map[string]any{"operationName": operationName, "config": config}
	InternalDeepMarshal(kwargs, &parameterMap)

	var httpOptions *HTTPOptions
	if config == nil || config.HTTPOptions == nil {
		httpOptions = &HTTPOptions{}
	} else {
		httpOptions = config.HTTPOptions
	}
	if httpOptions.Headers == nil {
		httpOptions.Headers = http.Header{}
	}
	var response = new(UploadToFileSearchStoreOperation)
	var responseMap map[string]any
	var fromConverter func(map[string]any, map[string]any, map[string]any) (map[string]any, error)
	var toConverter func(map[string]any, map[string]any, map[string]any) (map[string]any, error)
	if m.apiClient.ClientConfig().Backend == BackendVertexAI {
		toConverter = getOperationParametersToVertex

	} else {
		toConverter = getOperationParametersToMldev
		fromConverter = uploadToFileSearchStoreOperationFromMldev
	}

	body, err := toConverter(parameterMap, nil, parameterMap)
	if err != nil {
		return nil, err
	}

	var path string
	var urlParams map[string]any
	if _, ok := body["_url"]; ok {
		urlParams = body["_url"].(map[string]any)
		delete(body, "_url")
	}
	path, err = InternalFormatMap("{operationName}", urlParams)
	if err != nil {
		return nil, fmt.Errorf("invalid url params: %#v.\n%w", urlParams, err)
	}
	if _, ok := body["_query"]; ok {
		query, err := InternalCreateURLQuery(body["_query"].(map[string]any))
		if err != nil {
			return nil, err
		}
		path += "?" + query
		delete(body, "_query")
	}
	responseMap, err = sendRequest(ctx, m.apiClient, path, http.MethodGet, body, httpOptions)
	if err != nil {
		return nil, err
	}
	if fromConverter != nil {
		responseMap, err = fromConverter(responseMap, nil, parameterMap)
	}
	if err != nil {
		return nil, err
	}
	err = InternalMapToStruct(responseMap, response)
	if err != nil {
		return nil, err
	}

	if field, ok := reflect.TypeOf(response).Elem().FieldByName("SDKHTTPResponse"); ok {
		{
			if reflect.ValueOf(response).Elem().FieldByName("SDKHTTPResponse").IsValid() {
				{
					reflect.ValueOf(response).Elem().FieldByName("SDKHTTPResponse").Set(reflect.Zero(field.Type))
				}
			}
		}
	}

	return response, nil
}

func (m Operations) getImportFileOperation(ctx context.Context, operationName string, config *GetOperationConfig) (*ImportFileOperation, error) {
	parameterMap := make(map[string]any)

	kwargs := map[string]any{"operationName": operationName, "config": config}
	InternalDeepMarshal(kwargs, &parameterMap)

	var httpOptions *HTTPOptions
	if config == nil || config.HTTPOptions == nil {
		httpOptions = &HTTPOptions{}
	} else {
		httpOptions = config.HTTPOptions
	}
	if httpOptions.Headers == nil {
		httpOptions.Headers = http.Header{}
	}
	var response = new(ImportFileOperation)
	var responseMap map[string]any
	var fromConverter func(map[string]any, map[string]any, map[string]any) (map[string]any, error)
	var toConverter func(map[string]any, map[string]any, map[string]any) (map[string]any, error)
	if m.apiClient.ClientConfig().Backend == BackendVertexAI {
		toConverter = getOperationParametersToVertex

	} else {
		toConverter = getOperationParametersToMldev
		fromConverter = importFileOperationFromMldev
	}

	body, err := toConverter(parameterMap, nil, parameterMap)
	if err != nil {
		return nil, err
	}

	var path string
	var urlParams map[string]any
	if _, ok := body["_url"]; ok {
		urlParams = body["_url"].(map[string]any)
		delete(body, "_url")
	}
	path, err = InternalFormatMap("{operationName}", urlParams)
	if err != nil {
		return nil, fmt.Errorf("invalid url params: %#v.\n%w", urlParams, err)
	}
	if _, ok := body["_query"]; ok {
		query, err := InternalCreateURLQuery(body["_query"].(map[string]any))
		if err != nil {
			return nil, err
		}
		path += "?" + query
		delete(body, "_query")
	}
	responseMap, err = sendRequest(ctx, m.apiClient, path, http.MethodGet, body, httpOptions)
	if err != nil {
		return nil, err
	}
	if fromConverter != nil {
		responseMap, err = fromConverter(responseMap, nil, parameterMap)
	}
	if err != nil {
		return nil, err
	}
	err = InternalMapToStruct(responseMap, response)
	if err != nil {
		return nil, err
	}

	if field, ok := reflect.TypeOf(response).Elem().FieldByName("SDKHTTPResponse"); ok {
		{
			if reflect.ValueOf(response).Elem().FieldByName("SDKHTTPResponse").IsValid() {
				{
					reflect.ValueOf(response).Elem().FieldByName("SDKHTTPResponse").Set(reflect.Zero(field.Type))
				}
			}
		}
	}

	return response, nil
}

// GetVideosOperation retrieves the status and result of a long-running video generation operation.
//
// If the operation is still in progress, the returned GenerateVideosOperation
// will have Done set to false. If the operation has completed successfully,
// Done will be true, and the Result field will contain the result. If the
// operation failed, Done will be true, and the Error field will be populated.
func (m Operations) GetVideosOperation(ctx context.Context, operation *GenerateVideosOperation, config *GetOperationConfig) (*GenerateVideosOperation, error) {
	operationName := operation.Name
	if operationName == "" {
		return nil, fmt.Errorf("Operation name is empty")
	}
	if m.apiClient.clientConfig.Backend == BackendVertexAI {
		parts := strings.Split(operationName, "/operations/")
		if len(parts) > 1 {
			resourceName := parts[0]
			fetchPredictOperationConfig := &FetchPredictOperationConfig{}
			if config != nil {
				fetchPredictOperationConfig.HTTPOptions = config.HTTPOptions
			}
			return m.fetchPredictVideosOperation(ctx, operationName, resourceName, fetchPredictOperationConfig)
		} else {
			return nil, fmt.Errorf("Invalid operation name")
		}
	}
	return m.getVideosOperation(ctx, operationName, config)
}

// GetUploadToFileSearchStoreOperation retrieves the status and result of a long-running upload to file search store operation.
//
// If the operation is still in progress, the returned UploadToFileSearchStoreOperation
// will have Done set to false. If the operation has completed successfully,
// Done will be true, and the Result field will contain the result. If the
// operation failed, Done will be true, and the Error field will be populated.
func (m Operations) GetUploadToFileSearchStoreOperation(ctx context.Context, operation *UploadToFileSearchStoreOperation, config *GetOperationConfig) (*UploadToFileSearchStoreOperation, error) {
	operationName := operation.Name
	if operationName == "" {
		return nil, fmt.Errorf("Operation name is empty")
	}
	if m.apiClient.clientConfig.Backend == BackendVertexAI {
		return nil, fmt.Errorf("method GetUploadToFileSearchStoreOperation is only supported in Gemini Developer API mode, not in Gemini Enterprise Agent Platform mode. You can choose to use Gemini Developer client by setting ClientConfig.Backend to BackendGeminiAPI.")
	}
	return m.getUploadToFileSearchStoreOperation(ctx, operationName, config)
}

// GetImportFileOperation retrieves the status and result of a long-running import file to file search store operation.
//
// If the operation is still in progress, the returned ImportFileOperation
// will have Done set to false. If the operation has completed successfully,
// Done will be true, and the Result field will contain the result. If the
// operation failed, Done will be true, and the Error field will be populated.
func (m Operations) GetImportFileOperation(ctx context.Context, operation *ImportFileOperation, config *GetOperationConfig) (*ImportFileOperation, error) {
	operationName := operation.Name
	if operationName == "" {
		return nil, fmt.Errorf("Operation name is empty")
	}
	if m.apiClient.clientConfig.Backend == BackendVertexAI {
		return nil, fmt.Errorf("method GetUploadToFileSearchStoreOperation is only supported in Gemini Developer API mode, not in Gemini Enterprise Agent Platform mode. You can choose to use Gemini Developer client by setting ClientConfig.Backend to BackendGeminiAPI.")
	}
	return m.getImportFileOperation(ctx, operationName, config)
}
