// Package api provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
package api

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/oapi-codegen/runtime"
)

// ServerInterface represents all server handlers.
type ServerInterface interface {
	// Get admin status
	// (GET /api/v2/admin/status)
	AdminStatus(c *gin.Context)
	// Create user
	// (POST /api/v2/admin/users)
	CreateUser(c *gin.Context)
	// Get user by id
	// (GET /api/v2/admin/users/{id})
	UserById(c *gin.Context, id string)
	// Add paymails to user
	// (POST /api/v2/admin/users/{id}/paymails)
	AddPaymailToUser(c *gin.Context, id string)
	// Get shared config
	// (GET /api/v2/configs/shared)
	SharedConfig(c *gin.Context)
	// Get data for user
	// (GET /api/v2/data/{id})
	DataById(c *gin.Context, id string)
	// Get Merkleroots
	// (GET /api/v2/merkleroots)
	MerkleRoots(c *gin.Context, params MerkleRootsParams)
	// Get operations for user
	// (GET /api/v2/operations/search)
	SearchOperations(c *gin.Context, params SearchOperationsParams)
	// Record transaction outline
	// (POST /api/v2/transactions)
	RecordTransactionOutline(c *gin.Context)
	// Create transaction outline
	// (POST /api/v2/transactions/outlines)
	CreateTransactionOutline(c *gin.Context, params CreateTransactionOutlineParams)
	// Get current user
	// (GET /api/v2/users/current)
	CurrentUser(c *gin.Context)
}

// ServerInterfaceWrapper converts contexts to parameters.
type ServerInterfaceWrapper struct {
	Handler            ServerInterface
	HandlerMiddlewares []MiddlewareFunc
	ErrorHandler       func(*gin.Context, error, int)
}

type MiddlewareFunc func(c *gin.Context)

// AdminStatus operation middleware
func (siw *ServerInterfaceWrapper) AdminStatus(c *gin.Context) {

	c.Set(XPubAuthScopes, []string{"admin"})

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.AdminStatus(c)
}

// CreateUser operation middleware
func (siw *ServerInterfaceWrapper) CreateUser(c *gin.Context) {

	c.Set(XPubAuthScopes, []string{"admin"})

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.CreateUser(c)
}

// UserById operation middleware
func (siw *ServerInterfaceWrapper) UserById(c *gin.Context) {

	var err error

	// ------------- Path parameter "id" -------------
	var id string

	err = runtime.BindStyledParameterWithOptions("simple", "id", c.Param("id"), &id, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter id: %w", err), http.StatusBadRequest)
		return
	}

	c.Set(XPubAuthScopes, []string{"admin"})

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.UserById(c, id)
}

// AddPaymailToUser operation middleware
func (siw *ServerInterfaceWrapper) AddPaymailToUser(c *gin.Context) {

	var err error

	// ------------- Path parameter "id" -------------
	var id string

	err = runtime.BindStyledParameterWithOptions("simple", "id", c.Param("id"), &id, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter id: %w", err), http.StatusBadRequest)
		return
	}

	c.Set(XPubAuthScopes, []string{"admin"})

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.AddPaymailToUser(c, id)
}

// SharedConfig operation middleware
func (siw *ServerInterfaceWrapper) SharedConfig(c *gin.Context) {

	c.Set(XPubAuthScopes, []string{"admin", "user"})

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.SharedConfig(c)
}

// DataById operation middleware
func (siw *ServerInterfaceWrapper) DataById(c *gin.Context) {

	var err error

	// ------------- Path parameter "id" -------------
	var id string

	err = runtime.BindStyledParameterWithOptions("simple", "id", c.Param("id"), &id, runtime.BindStyledParameterOptions{Explode: false, Required: true})
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter id: %w", err), http.StatusBadRequest)
		return
	}

	c.Set(XPubAuthScopes, []string{"user"})

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.DataById(c, id)
}

// MerkleRoots operation middleware
func (siw *ServerInterfaceWrapper) MerkleRoots(c *gin.Context) {

	var err error

	c.Set(XPubAuthScopes, []string{"user"})

	// Parameter object where we will unmarshal all parameters from the context
	var params MerkleRootsParams

	// ------------- Optional query parameter "batchSize" -------------

	err = runtime.BindQueryParameter("form", true, false, "batchSize", c.Request.URL.Query(), &params.BatchSize)
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter batchSize: %w", err), http.StatusBadRequest)
		return
	}

	// ------------- Optional query parameter "lastEvaluatedKey" -------------

	err = runtime.BindQueryParameter("form", true, false, "lastEvaluatedKey", c.Request.URL.Query(), &params.LastEvaluatedKey)
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter lastEvaluatedKey: %w", err), http.StatusBadRequest)
		return
	}

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.MerkleRoots(c, params)
}

// SearchOperations operation middleware
func (siw *ServerInterfaceWrapper) SearchOperations(c *gin.Context) {

	var err error

	c.Set(XPubAuthScopes, []string{"user"})

	// Parameter object where we will unmarshal all parameters from the context
	var params SearchOperationsParams

	// ------------- Optional query parameter "page" -------------

	err = runtime.BindQueryParameter("form", true, false, "page", c.Request.URL.Query(), &params.Page)
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter page: %w", err), http.StatusBadRequest)
		return
	}

	// ------------- Optional query parameter "size" -------------

	err = runtime.BindQueryParameter("form", true, false, "size", c.Request.URL.Query(), &params.Size)
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter size: %w", err), http.StatusBadRequest)
		return
	}

	// ------------- Optional query parameter "sort" -------------

	err = runtime.BindQueryParameter("form", true, false, "sort", c.Request.URL.Query(), &params.Sort)
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter sort: %w", err), http.StatusBadRequest)
		return
	}

	// ------------- Optional query parameter "sortBy" -------------

	err = runtime.BindQueryParameter("form", true, false, "sortBy", c.Request.URL.Query(), &params.SortBy)
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter sortBy: %w", err), http.StatusBadRequest)
		return
	}

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.SearchOperations(c, params)
}

// RecordTransactionOutline operation middleware
func (siw *ServerInterfaceWrapper) RecordTransactionOutline(c *gin.Context) {

	c.Set(XPubAuthScopes, []string{"user"})

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.RecordTransactionOutline(c)
}

// CreateTransactionOutline operation middleware
func (siw *ServerInterfaceWrapper) CreateTransactionOutline(c *gin.Context) {

	var err error

	c.Set(XPubAuthScopes, []string{"user"})

	// Parameter object where we will unmarshal all parameters from the context
	var params CreateTransactionOutlineParams

	// ------------- Optional query parameter "format" -------------

	err = runtime.BindQueryParameter("form", true, false, "format", c.Request.URL.Query(), &params.Format)
	if err != nil {
		siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter format: %w", err), http.StatusBadRequest)
		return
	}

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.CreateTransactionOutline(c, params)
}

// CurrentUser operation middleware
func (siw *ServerInterfaceWrapper) CurrentUser(c *gin.Context) {

	c.Set(XPubAuthScopes, []string{"user"})

	for _, middleware := range siw.HandlerMiddlewares {
		middleware(c)
		if c.IsAborted() {
			return
		}
	}

	siw.Handler.CurrentUser(c)
}

// GinServerOptions provides options for the Gin server.
type GinServerOptions struct {
	BaseURL      string
	Middlewares  []MiddlewareFunc
	ErrorHandler func(*gin.Context, error, int)
}

// RegisterHandlers creates http.Handler with routing matching OpenAPI spec.
func RegisterHandlers(router gin.IRouter, si ServerInterface) {
	RegisterHandlersWithOptions(router, si, GinServerOptions{})
}

// RegisterHandlersWithOptions creates http.Handler with additional options
func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) {
	errorHandler := options.ErrorHandler
	if errorHandler == nil {
		errorHandler = func(c *gin.Context, err error, statusCode int) {
			c.JSON(statusCode, gin.H{"msg": err.Error()})
		}
	}

	wrapper := ServerInterfaceWrapper{
		Handler:            si,
		HandlerMiddlewares: options.Middlewares,
		ErrorHandler:       errorHandler,
	}

	router.GET(options.BaseURL+"/api/v2/admin/status", wrapper.AdminStatus)
	router.POST(options.BaseURL+"/api/v2/admin/users", wrapper.CreateUser)
	router.GET(options.BaseURL+"/api/v2/admin/users/:id", wrapper.UserById)
	router.POST(options.BaseURL+"/api/v2/admin/users/:id/paymails", wrapper.AddPaymailToUser)
	router.GET(options.BaseURL+"/api/v2/configs/shared", wrapper.SharedConfig)
	router.GET(options.BaseURL+"/api/v2/data/:id", wrapper.DataById)
	router.GET(options.BaseURL+"/api/v2/merkleroots", wrapper.MerkleRoots)
	router.GET(options.BaseURL+"/api/v2/operations/search", wrapper.SearchOperations)
	router.POST(options.BaseURL+"/api/v2/transactions", wrapper.RecordTransactionOutline)
	router.POST(options.BaseURL+"/api/v2/transactions/outlines", wrapper.CreateTransactionOutline)
	router.GET(options.BaseURL+"/api/v2/users/current", wrapper.CurrentUser)
}
