/*
 * Responses Test
 *
 * This specification is intended for testing purposes. It demonstrates various response media types.
 *
 * API version: 1.0.0
 * Generated by: OpenAPI Generator (https://openapi-generator.tech)
 */

package openapi

import (
	"bytes"
	"compress/gzip"
	"compress/zlib"
	"encoding/json"
	"fmt"
	"net/http"
	"os"

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

type TestAPI struct {
}

// Get /v2/response/application/json/object
// Check response type application-json object
func (api *TestAPI) ApplicationJsonEncodedObjectResponse(c *gin.Context) {
	resp := ApplicationJsonObjectResponse200Response{
		Status: "OK",
		Value:  22,
	}

	jsonBytes, err := json.Marshal(resp)
	if err != nil {
		c.String(http.StatusInternalServerError, "failed to marshal JSON")
		return
	}

	// Step1: Gzip compress
	var gzipBuf bytes.Buffer
	gz := gzip.NewWriter(&gzipBuf)
	if _, err := gz.Write(jsonBytes); err != nil {
		c.String(http.StatusInternalServerError, "gzip compression failed")
		return
	}
	if err := gz.Close(); err != nil {
		c.String(http.StatusInternalServerError, "gzip close failed")
		return
	}

	// Step2: Deflate compress
	var deflateBuf bytes.Buffer
	def := zlib.NewWriter(&deflateBuf)
	if _, err := def.Write(gzipBuf.Bytes()); err != nil {
		c.String(http.StatusInternalServerError, "deflate compression failed")
		return
	}
	if err := def.Close(); err != nil {
		c.String(http.StatusInternalServerError, "deflate close failed")
		return
	}

	// List in order of compression application
	c.Header("Content-Encoding", "gzip, deflate")
	c.Data(http.StatusOK, "application/json", deflateBuf.Bytes())
}

// Get /v2/response/application/json/string
// Check response type application-json string
func (api *TestAPI) ApplicationJsonStringResponse(c *gin.Context) {
	c.JSON(200, gin.H{"status": "OK"})
}

// Get /v2/response/application/json/array
// Check response type application-json array
func (api *TestAPI) ApplicationJsonArrayResponse(c *gin.Context) {
	userRes1 := User{Name: "user1", Id: 1}
	userRes2 := User{Name: "user2", Id: 2}

	users := []User{userRes1, userRes2}
	c.JSON(200, users)
}

// Get /v2/response/application/json/map
// Check response type application-json map
func (api *TestAPI) ApplicationJsonMapResponse(c *gin.Context) {
	userRes1 := User{Name: "user1", Id: 1}
	userRes2 := User{Name: "user2", Id: 2}

	c.JSON(200, gin.H{"first": userRes1, "second": userRes2})
}

// Get /v2/response/text/plain/string
// Check response type text/plain string
func (api *TestAPI) TextPlainStringResponse(c *gin.Context) {
	c.Data(200, "text/plain", []byte("Hello plain text"))
}

// Get /v2/response/application/pdf/inline/{fileId}
// Serve pdf inline
func (api *TestAPI) ApplicationPdfInlineResponse(c *gin.Context) {
	filePath := "./" + c.Param("fileId")

	pdfContent, err := os.ReadFile(filePath)
	if err != nil {
		c.String(500, fmt.Sprintf("Failed to read file: %v", err))
		return
	}

	// Send pdf bytes
	c.Data(200, "application/pdf", pdfContent)
}

// Get /v2/response/application/pdf/save/{fileId}
// Save pdf file
func (api *TestAPI) ApplicationPdfSaveResponse(c *gin.Context) {
	filePath := "./" + c.Param("fileId")

	pdfContent, err := os.ReadFile(filePath)
	if err != nil {
		c.String(500, fmt.Sprintf("Failed to read file: %v", err))
		return
	}

	// Force download
	c.Header("Content-Disposition", `attachment; filename="example1.pdf"`)

	// Send pdf bytes
	c.Data(200, "application/pdf", pdfContent) // Set the Content-Type header
}

// Get /v2/response/application/pdf/save/encoded/{fileId}
// Save encoded pdf file
func (api *TestAPI) ApplicationEncodedPdfSaveResponse(c *gin.Context) {
	filePath := "./" + c.Param("fileId")

	pdfContent, err := os.ReadFile(filePath)
	if err != nil {
		c.String(500, fmt.Sprintf("Failed to read file: %v", err))
		return
	}

	// Compress the content with gzip
	var buf bytes.Buffer
	gz := gzip.NewWriter(&buf)
	if _, err := gz.Write(pdfContent); err != nil {
		c.String(http.StatusInternalServerError, "gzip compression failed")
		return
	}
	if err := gz.Close(); err != nil {
		c.String(http.StatusInternalServerError, "gzip close failed")
		return
	}

	// Force download
	c.Header("Content-Disposition", `attachment; filename="compressed_example1.pdf"`)

	// Set encoing header
	c.Header("Content-Encoding", "gzip")

	// Send pdf bytes
	c.Data(200, "application/pdf", buf.Bytes()) // Set the Content-Type header
}

// Get /v2/response/image/inline/{imageId}
// Get an image by ID
func (api *TestAPI) InlineImageResponse(c *gin.Context) {
	imageID := c.Param("imageId")

	var filePath string
	var contentType string

	switch imageID {
	case "jpegImage":
		filePath = "./testImage.jpg"
		contentType = "image/jpeg"
	//case "pngImage":
	default:
		// Default to PNG if not specified or not jpeg
		filePath = "./testImage.png"
		contentType = "image/png"
	}

	// Read image file
	data, err := os.ReadFile(filePath)
	if err != nil {
		c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to read image: %v", err))
		return
	}

	// Send image as inline content
	c.Data(http.StatusOK, contentType, data)
}

// Get /v2/response/image/save/{imageId}
// Get an image by ID and download it
func (api *TestAPI) SaveImageResponse(c *gin.Context) {
	imageID := c.Param("imageId")

	var filePath string
	var contentType string
	var contentDisposition string

	switch imageID {
	case "jpegImage":
		filePath = "./testImage.jpg"
		contentType = "image/jpeg"
		contentDisposition = `attachment; filename="example2.jpg"`
	//case "pngImage":
	default:
		// Default to png if not not jpeg or not specified
		filePath = "./testImage.png"
		contentType = "image/png"
		contentDisposition = `attachment; filename="example3.png"`
	}

	// Read image file
	data, err := os.ReadFile(filePath)
	if err != nil {
		c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to read image: %v", err))
		return
	}

	// Force download
	c.Header("Content-Disposition", contentDisposition)
	// Send image as inline content
	c.Data(http.StatusOK, contentType, data)
}

func (api *TestAPI) ApplicationOctetStreamResponse(c *gin.Context) {
	filePath := "./" + c.Param("fileId")

	binContent, err := os.ReadFile(filePath)
	if err != nil {
		c.String(500, fmt.Sprintf("Failed to read file: %v", err))
		return
	}

	// Force download
	c.Header("Content-Disposition", `attachment; filename="example.bin"`)

	// Send pdf bytes
	c.Data(200, "application/pdf", binContent) // Set the Content-Type header
}

func (api *TestAPI) EmptyResponse(c *gin.Context) {
	// Set HTTP status 204 (No Content)
	c.Status(204)
}

func (api *TestAPI) ContentDispositionCheck(c *gin.Context) {
	binContent, err := os.ReadFile("./test.bin")
	if err != nil {
		c.String(http.StatusInternalServerError, fmt.Sprintf("Failed to read file: %v", err))
		return
	}

	// Parse the parameters to extract the 'filename=' and 'filename*='
	// values
	filename := c.Query("filename")
	extFilename := c.Query("extFilename")
	if filename == "" && extFilename == "" {
		c.String(http.StatusBadRequest, "No filename or extFilename parameter specified!")
		return
	}

	contentDisposition := "Attachment " // intentionally added whitespace in the end
	if filename != "" {
		contentDisposition += "; FILENAME=" + filename
	}
	if extFilename != "" {
		contentDisposition += "; FileName*=" + extFilename
	}

	c.Header("Content-Disposition", contentDisposition)
	c.Data(http.StatusOK, "application/octet-stream", binContent)
}
