package handlers

import (
	"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
	"github.com/gofiber/fiber/v2"
)

type launchVirtualGameReq struct {
	GameID   string `json:"game_id" validate:"required" example:"crash_001"`
	Currency string `json:"currency" validate:"required,len=3" example:"USD"`
	Mode     string `json:"mode" validate:"required,oneof=fun real" example:"real"`
}

type launchVirtualGameRes struct {
	LaunchURL string `json:"launch_url"`
}

// LaunchVirtualGame godoc
// @Summary Launch a PopOK virtual game
// @Description Generates a URL to launch a PopOK game
// @Tags virtual-game
// @Accept json
// @Produce json
// @Security Bearer
// @Param launch body launchVirtualGameReq true "Game launch details"
// @Success 200 {object} launchVirtualGameRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /virtual-game/launch [post]
func (h *Handler) LaunchVirtualGame(c *fiber.Ctx) error {

	userID, ok := c.Locals("user_id").(int64)
	if !ok || userID == 0 {
		h.logger.Error("Invalid user ID in context")
		return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
	}

	var req launchVirtualGameReq
	if err := c.BodyParser(&req); err != nil {
		h.logger.Error("Failed to parse LaunchVirtualGame request", "error", err)
		return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
	}

	if valErrs, ok := h.validator.Validate(c, req); !ok {
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
	}

	url, err := h.virtualGameSvc.GenerateGameLaunchURL(c.Context(), userID, req.GameID, req.Currency, req.Mode)
	if err != nil {
		h.logger.Error("Failed to generate game launch URL", "userID", userID, "gameID", req.GameID, "error", err)
		return fiber.NewError(fiber.StatusInternalServerError, "Failed to launch game")
	}

	res := launchVirtualGameRes{LaunchURL: url}
	return response.WriteJSON(c, fiber.StatusOK, "Game launched successfully", res, nil)
}

// HandleVirtualGameCallback godoc
// @Summary Handle PopOK game callback
// @Description Processes callbacks from PopOK for game events
// @Tags virtual-game
// @Accept json
// @Produce json
// @Param callback body domain.PopOKCallback true "Callback data"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /virtual-game/callback [post]
func (h *Handler) HandleVirtualGameCallback(c *fiber.Ctx) error {
	var callback domain.PopOKCallback
	if err := c.BodyParser(&callback); err != nil {
		h.logger.Error("Failed to parse callback", "error", err)
		return fiber.NewError(fiber.StatusBadRequest, "Invalid callback data")
	}

	if err := h.virtualGameSvc.HandleCallback(c.Context(), &callback); err != nil {
		h.logger.Error("Failed to handle callback", "transactionID", callback.TransactionID, "error", err)
		return fiber.NewError(fiber.StatusInternalServerError, "Failed to process callback")
	}

	return response.WriteJSON(c, fiber.StatusOK, "Callback processed successfully", nil, nil)
}

func (h *Handler) HandlePlayerInfo(c *fiber.Ctx) error {
	var req domain.PopOKPlayerInfoRequest
	if err := c.BodyParser(&req); err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
	}

	resp, err := h.virtualGameSvc.GetPlayerInfo(c.Context(), &req)
	if err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, err.Error())
	}

	return response.WriteJSON(c, fiber.StatusOK, "Player info retrieved", resp, nil)
}

func (h *Handler) HandleBet(c *fiber.Ctx) error {
	var req domain.PopOKBetRequest
	if err := c.BodyParser(&req); err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid bet request")
	}

	resp, err := h.virtualGameSvc.ProcessBet(c.Context(), &req)
	if err != nil {
		code := fiber.StatusInternalServerError
		if err.Error() == "invalid token" {
			code = fiber.StatusUnauthorized
		} else if err.Error() == "insufficient balance" {
			code = fiber.StatusBadRequest
		}
		return fiber.NewError(code, err.Error())
	}

	return response.WriteJSON(c, fiber.StatusOK, "Bet processed", resp, nil)
}

func (h *Handler) HandleWin(c *fiber.Ctx) error {
	var req domain.PopOKWinRequest
	if err := c.BodyParser(&req); err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid win request")
	}

	resp, err := h.virtualGameSvc.ProcessWin(c.Context(), &req)
	if err != nil {
		code := fiber.StatusInternalServerError
		if err.Error() == "invalid token" {
			code = fiber.StatusUnauthorized
		}
		return fiber.NewError(code, err.Error())
	}

	return response.WriteJSON(c, fiber.StatusOK, "Win processed", resp, nil)
}

func (h *Handler) HandleCancel(c *fiber.Ctx) error {
	var req domain.PopOKCancelRequest
	if err := c.BodyParser(&req); err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid cancel request")
	}

	resp, err := h.virtualGameSvc.ProcessCancel(c.Context(), &req)
	if err != nil {
		code := fiber.StatusInternalServerError
		switch err.Error() {
		case "invalid token":
			code = fiber.StatusUnauthorized
		case "original bet not found", "invalid original transaction":
			code = fiber.StatusBadRequest
		}
		return fiber.NewError(code, err.Error())
	}

	return response.WriteJSON(c, fiber.StatusOK, "Cancel processed", resp, nil)
}
