package Astrologer

import (
	config "astrology-api/configs"
	dto_astrologer "astrology-api/dto_astrologer"
	"astrology-api/helpers"
	services_astrologer "astrology-api/services_astrologer"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"

	"log"
)

///////////////////////////////////////////////////////////
// Wallet Controller
///////////////////////////////////////////////////////////

type WalletController struct {
	service services_astrologer.WalletService
}

///////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////

func NewWalletController(
	service services_astrologer.WalletService,
) *WalletController {
	log.Printf("config.DB = %v", config.DB)
	return &WalletController{
		service: service,
	}
}

///////////////////////////////////////////////////////////
// Get Wallet Summary
// GET /api/astrologer/wallet
///////////////////////////////////////////////////////////

func (c *WalletController) GetWallet(ctx *gin.Context) {

	//------------------------------------------------
	// Get Logged-in User
	//------------------------------------------------

	userID := ctx.MustGet("user_id").(uint)

	//------------------------------------------------
	// Get Wallet
	//------------------------------------------------

	response, err := c.service.GetWallet(userID)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	//------------------------------------------------
	// Success Response
	//------------------------------------------------

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Wallet fetched successfully.",
			response,
		),
	)
}

///////////////////////////////////////////////////////////
// Dummy reference to avoid unused import error
// (remove when remaining controller methods are added)
///////////////////////////////////////////////////////////

var (
	_ = dto_astrologer.WithdrawRequest{}
)

///////////////////////////////////////////////////////////
// Get Wallet Transactions
// GET /api/astrologer/wallet/transactions
///////////////////////////////////////////////////////////

func (c *WalletController) GetTransactions(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	//------------------------------------------------
	// Query Parameters
	//------------------------------------------------

	page := 1
	limit := 10
	filter := ctx.DefaultQuery("type", "ALL")

	if value := ctx.Query("page"); value != "" {

		if parsed, err := strconv.Atoi(value); err == nil && parsed > 0 {
			page = parsed
		}
	}

	if value := ctx.Query("limit"); value != "" {

		if parsed, err := strconv.Atoi(value); err == nil && parsed > 0 {
			limit = parsed
		}
	}

	//------------------------------------------------
	// Service
	//------------------------------------------------

	transactions, total, err := c.service.GetTransactions(
		userID,
		filter,
		page,
		limit,
	)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	//------------------------------------------------
	// Response
	//------------------------------------------------

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Wallet transactions fetched successfully.",
			gin.H{
				"transactions": transactions,
				"page":         page,
				"limit":        limit,
				"total":        total,
			},
		),
	)
}

///////////////////////////////////////////////////////////
// Get Transaction Details
// GET /api/astrologer/wallet/transaction/:id
///////////////////////////////////////////////////////////

func (c *WalletController) GetTransactionByID(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	//------------------------------------------------
	// Transaction ID
	//------------------------------------------------

	id, err := strconv.ParseUint(
		ctx.Param("id"),
		10,
		64,
	)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse("invalid transaction id"),
		)

		return
	}

	//------------------------------------------------
	// Service
	//------------------------------------------------

	response, err := c.service.GetTransactionByID(
		userID,
		uint(id),
	)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	//------------------------------------------------
	// Success
	//------------------------------------------------

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Transaction details fetched successfully.",
			response,
		),
	)
}

///////////////////////////////////////////////////////////
// Withdraw Config
// GET /api/astrologer/wallet/withdraw/config
///////////////////////////////////////////////////////////
//
// Everything the withdraw screen needs before an amount is entered: the
// available balance, the minimum and the quick-amount chips, both withdraw
// types with the charges that apply to them, and the astrologer's saved UPI
// and bank account.

func (c *WalletController) GetWithdrawConfig(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	response, err := c.service.GetWithdrawConfig(userID)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Withdraw configuration fetched successfully.",
			response,
		),
	)
}

///////////////////////////////////////////////////////////
// Withdraw Preview
// POST /api/astrologer/wallet/withdraw/preview
///////////////////////////////////////////////////////////
//
// The Summary card. Nothing is written, but the same validation runs as on
// the create call, so an amount that previews cleanly will not be refused
// when the astrologer confirms it.

func (c *WalletController) PreviewWithdraw(ctx *gin.Context) {

	var req dto_astrologer.WithdrawRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	userID := ctx.MustGet("user_id").(uint)

	response, err := c.service.PreviewWithdraw(
		userID,
		req,
	)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Withdraw summary calculated successfully.",
			response,
		),
	)
}

///////////////////////////////////////////////////////////
// Withdraw Request
// POST /api/astrologer/wallet/withdraw
///////////////////////////////////////////////////////////
//
// Body: { "amount": 5000, "withdrawType": "GENERAL"|"INSTANT",
//         "paymentMethod": "UPI"|"BANK" }
//
// Payout details are not accepted from the client — they are read from the
// astrologer's saved bank account for the chosen method.

func (c *WalletController) Withdraw(ctx *gin.Context) {

	//------------------------------------------------
	// Request Model
	//------------------------------------------------

	var req dto_astrologer.WithdrawRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	//------------------------------------------------
	// Logged In User
	//------------------------------------------------

	userID := ctx.MustGet("user_id").(uint)

	//------------------------------------------------
	// Withdraw Request
	//------------------------------------------------

	response, err := c.service.Withdraw(
		userID,
		req,
	)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	//------------------------------------------------
	// Success Response
	//------------------------------------------------

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			response.Message,
			response,
		),
	)
}

///////////////////////////////////////////////////////////
// Get Withdraw History
// GET /api/astrologer/wallet/withdraw-history
///////////////////////////////////////////////////////////

func (c *WalletController) GetWithdrawHistory(ctx *gin.Context) {

	//------------------------------------------------
	// Logged In User
	//------------------------------------------------

	userID := ctx.MustGet("user_id").(uint)

	//------------------------------------------------
	// Service
	//------------------------------------------------

	response, err := c.service.GetWithdrawHistory(userID)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	//------------------------------------------------
	// Success
	//------------------------------------------------

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Withdraw history fetched successfully.",
			response,
		),
	)
}

///////////////////////////////////////////////////////////
// Get Settlement History
// GET /api/astrologer/wallet/settlement-history
///////////////////////////////////////////////////////////

func (c *WalletController) GetSettlementHistory(ctx *gin.Context) {

	//------------------------------------------------
	// Logged In User
	//------------------------------------------------

	userID := ctx.MustGet("user_id").(uint)

	//------------------------------------------------
	// Service
	//------------------------------------------------

	response, err := c.service.GetSettlementHistory(userID)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	//------------------------------------------------
	// Success
	//------------------------------------------------

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Settlement history fetched successfully.",
			response,
		),
	)
}
