package handler

import (
	"net/http"

	"galaxy/model/order"
	"galaxy/model/rest"

	"galaxy/game/internal/repo"

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

func PutOrderHandler(c *gin.Context, executor CommandExecutor) {
	var cmd rest.Command
	if errorResponse(c, c.ShouldBindJSON(&cmd)) {
		return
	}

	// An empty `cmd` array is a valid PUT: the client clears its
	// local order draft and expects the server to mirror that
	// state. The engine stores the empty batch so the next GET
	// returns the same empty list with the new `updatedAt`.
	commands := make([]order.DecodableCommand, len(cmd.Commands))
	for i := range cmd.Commands {
		command, err := repo.ParseOrder(cmd.Commands[i], validateCommand)
		if errorResponse(c, err) {
			return
		}
		commands[i] = command
	}

	result, err := executor.ValidateOrder(cmd.Actor, commands...)
	if errorResponse(c, err) {
		return
	}

	c.JSON(http.StatusAccepted, result)
}

type orderParam struct {
	Player string `form:"player" binding:"required,notblank"`
	Turn   int    `form:"turn" binding:"gte=0"`
}

func GetOrderHandler(c *gin.Context, executor CommandExecutor) {
	p := &orderParam{}
	// ShouldBindQuery surfaces both validator failures and strconv parse
	// errors; both are client-side faults, so 400 is the correct mapping.
	if err := c.ShouldBindQuery(p); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	o, ok, err := executor.FetchOrder(p.Player, uint(p.Turn))
	if errorResponse(c, err) {
		return
	}
	if !ok {
		// no order has been previously stored by the player for this turn
		c.Status(http.StatusNoContent)
		return
	}

	c.JSON(http.StatusOK, o)
}
