/*
 * Operation Parameters Test
 *
 * This specification is intended for testing purposes. It demonstrates a wide range of content types for requestBody. The goal is to verify correct url for each case.
 *
 * API version: 1.0.0
 * Generated by: OpenAPI Generator (https://openapi-generator.tech)
 */

package openapi

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

	"github.com/gin-gonic/gin"
)

type TestAPI struct {
}

// Post /v2/reqBody/octetstream/binaryType
// Test body parameter
func (api *TestAPI) BinaryType(c *gin.Context) {
	// Optional: limit request body size to prevent abuse
	c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 10<<20) // 10MB limit

	// Read the raw binary data
	data, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.String(http.StatusBadRequest, fmt.Sprintf("Error reading data: %v", err))
		return
	}

	fileContent := string(data)
	c.JSON(http.StatusOK, gin.H{"file-content": fileContent, "header": c.Request.Header, "bytes": data})
}

// Post /v2/reqBody/appjson/array/postApplicationJsonArray
// Put request-body, application-json, array
func (api *TestAPI) PostApplicationJsonArray(c *gin.Context) {
	var requestUsers any

	if err := c.ShouldBindJSON(&requestUsers); err != nil {
		fmt.Println("PostApplicationJsonArray: Error of reading json or empty json!", err)
	}

	// Here just check we can parse ANY block to array of users
	bytes, err := json.Marshal(requestUsers)
	if err != nil {
		fmt.Println("Failed to marshal: %w", err)
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	var users []User
	if err := json.Unmarshal(bytes, &users); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"users": requestUsers, "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/bool/postApplicationJsonBool
// Post request-body, application-json, boolean
func (api *TestAPI) PostApplicationJsonBool(c *gin.Context) {
	var requestBody bool
	if err := c.ShouldBindJSON(&requestBody); err != nil {
		fmt.Println("PostApplicationJsonBool: Error of reading json!", err)
	}
	c.JSON(http.StatusOK, gin.H{"bool": requestBody, "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/integer/postApplicationJsonInt
// Post request-body, application-json, integer
func (api *TestAPI) PostApplicationJsonInt(c *gin.Context) {
	var requestBody any
	if err := c.ShouldBindJSON(&requestBody); err != nil {
		fmt.Println("PostApplicationJsonInt: Error of reading json!", err)
	}
	c.JSON(http.StatusOK, gin.H{"integer": requestBody, "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/object/postApplicationJsonMap
// Post request-body, application-json, map of object
func (api *TestAPI) PostApplicationJsonMap(c *gin.Context) {
	var requestBody any
	if err := c.BindJSON(&requestBody); err != nil {
		fmt.Println("PostApplicationJsonMap: Error of reading json!", err)
	}
	c.JSON(http.StatusOK, gin.H{"nested-object": requestBody, "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/object/postApplicationJsonObject
// Post request-body, application-json, object
func (api *TestAPI) PostApplicationJsonObject(c *gin.Context) {
	var requestBody User
	if err := c.BindJSON(&requestBody); err != nil {
		fmt.Println("PostApplicationJsonObject: Error of reading json!", err)
	}
	c.JSON(http.StatusOK, gin.H{"json-object": requestBody, "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/object/postApplicationJsonSeveralObjects
// Post request-body, application-json, object
func (api *TestAPI) PostApplicationJsonSeveralObjects(c *gin.Context) {
	var requestBody any
	if err := c.BindJSON(&requestBody); err != nil {
		fmt.Println("PostApplicationJsonSeveralObjects: Error of reading json!", err)
	}
	c.JSON(http.StatusOK, gin.H{"nested-object": requestBody, "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/postClosedInlineEmptyJsonObject
// post inline empty Json object, which closed for extending.
func (api *TestAPI) PostClosedInlineEmptyJsonObject(c *gin.Context) {
	// Optional: limit request body size to prevent abuse
	c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 10<<20) // 10MB limit

	// Read the raw binary data
	body, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.String(http.StatusBadRequest, fmt.Sprintf("Error reading data: %v", err))
		return
	}

	c.JSON(http.StatusOK, gin.H{"empty-json-object": string(body), "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/postOpenedInlineEmptyJsonObject
// post inline empty Json object
func (api *TestAPI) PostOpenedInlineEmptyJsonObject(c *gin.Context) {
	// Optional: limit request body size to prevent abuse
	c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 10<<20) // 10MB limit

	// Read the raw binary data
	body, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.String(http.StatusBadRequest, fmt.Sprintf("Error reading data: %v", err))
		return
	}

	c.JSON(http.StatusOK, gin.H{"empty-json-object": string(body), "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/postNamedEmptyJsonObject
// post named empty Json object
func (api *TestAPI) PostNamedEmptyJsonObject(c *gin.Context) {
	// Optional: limit request body size to prevent abuse
	c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 10<<20) // 10MB limit

	// Read the raw binary data
	body, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.String(http.StatusBadRequest, fmt.Sprintf("Error reading data: %v", err))
		return
	}

	c.JSON(http.StatusOK, gin.H{"empty-json-object": string(body), "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/postNamedNestedEmptyJsonObject
func (api *TestAPI) PostNamedNestedEmptyJsonObject(c *gin.Context) {
	var requestBody any
	if err := c.BindJSON(&requestBody); err != nil {
		fmt.Println("PostNamedNestedEmptyJsonObject: Error of reading json!", err)
	}
	c.JSON(http.StatusOK, gin.H{"nested-object": requestBody, "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/postEmptyJsonSchema
// post Empty Json schema
func (api *TestAPI) PostEmptyJsonSchema(c *gin.Context) {
	var requestBody any
	if err := c.BindJSON(&requestBody); err != nil {
		fmt.Println("PostEmptyJsonSchema: Error of reading json!", err)
	}
	fmt.Println("PostEmptyJsonSchema: requestBody = ", requestBody)
	c.JSON(http.StatusOK, gin.H{"jsonvalue": requestBody, "header": c.Request.Header})
}

// Post /v2/reqBody/appjson/string/postApplicationJsonString
// Get request-body, application-json, string
func (api *TestAPI) PostApplicationJsonString(c *gin.Context) {
	// in case of null json, ShouldBindJSON return empty string without errors
	// but we want to double-check that it's literal null
	body, err := io.ReadAll(c.Request.Body)
	if err != nil {
		fmt.Println("PostApplicationJsonString: Error of reading request body!", err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "unable to read string body"})
		return
	}

	// Restore body so to bind later if needed
	c.Request.Body = io.NopCloser(bytes.NewBuffer(body))

	// Check for literal null
	if bytes.Equal(bytes.TrimSpace(body), []byte("null")) {
		c.JSON(http.StatusOK, gin.H{"json-string": "null", "header": c.Request.Header})
		return
	}

	// Check the case when optional string was not sent as a parameter
	if bytes.Equal(bytes.TrimSpace(body), []byte("")) {
		c.JSON(http.StatusOK, gin.H{"json-string": "", "header": c.Request.Header})
		return
	}

	var requestBody string
	if err := c.ShouldBindJSON(&requestBody); err != nil {
		fmt.Println("PostApplicationJsonString: Error of reading json", err)
	}
	c.JSON(http.StatusOK, gin.H{"json-string": requestBody, "header": c.Request.Header})
}

// Post /v2/reqBody/string/postPlainTextType
// Post a simple text, like a user input
func (api *TestAPI) PostPlainTextType(c *gin.Context) {
	bodyBytes, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "could not read a Plain Text."})
		return
	}

	plainText := string(bodyBytes)
	c.JSON(http.StatusOK, gin.H{"status": plainText, "header": c.Request.Header})
}

// Post /v2/reqBody/urlencoded/postUrlEncodedFields
// post Url Encoded simple key-value pairs
func (api *TestAPI) PostUrlEncodedFields(c *gin.Context) {
	visits := c.PostFormArray("visits")
	name := c.PostForm("name")
	status := c.PostForm("status")
	availability := c.PostForm("availability")
	data := c.PostForm("mapfield")

	c.JSON(http.StatusOK, gin.H{"visits": visits, "name": name, "status": status, "availability": availability, "mapfield": data, "header": c.Request.Header})
}

// Post /v2/reqBody/urlencoded/postUrlEncodedObject
// post Url Encoded simple key-value pairs
func (api *TestAPI) PostUrlEncodedObject(c *gin.Context) {
	username := c.PostForm("name")
	userstatus := c.PostForm("status")
	userage := c.PostForm("age")

	c.JSON(http.StatusOK, gin.H{"username": username, "status": userstatus, "age": userage, "header": c.Request.Header})
}

// Post /v2/reqBody/urlencoded/postUrlEncodedNestedObject
// post Url Encoded simple key-value pairs
func (api *TestAPI) PostUrlEncodedNestedObject(c *gin.Context) {
	username := c.PostForm("user")
	userstatus := c.PostForm("comment")

	c.JSON(http.StatusOK, gin.H{"user": username, "comment": userstatus, "header": c.Request.Header})
}

// Post /v2/reqBody/multipart/postMultiPartData
// post multi part data
func (api *TestAPI) PostMultiPartData(c *gin.Context) {
	id := c.PostForm("formId")
	index := c.PostForm("formIndex")
	users := c.PostFormArray("formAddresses")
	userObject := c.PostForm("formObject")
	userMap := c.PostForm("formMap")

	//Get the file from the form input
	file, _, err := c.Request.FormFile("formProfileImage")
	if err != nil {
		// HERE it is ok for the second call, because we test here sending empty fields and NON empty header
		c.JSON(http.StatusOK, gin.H{"header": c.Request.Header})
		return
	}
	defer file.Close()

	// Read binary data
	fileData, err := io.ReadAll(file)
	if err != nil {
		fmt.Println("Error of reading bynary data: ", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read file"})
		return
	}

	fileContent := string(fileData)
	c.JSON(http.StatusOK, gin.H{"formId": id, "formAddresses": users, "formIndex": index,
		"formObject": userObject, "formMap": userMap, "formProfileImage": fileContent, "header": c.Request.Header})
}
