package controller

import (
	"campaign-pool-be/app/module/ebooks/service"
	usersRepository "campaign-pool-be/app/module/users/repository"
	"campaign-pool-be/utils/paginator"
	"strconv"

	"github.com/gofiber/fiber/v2"
	"github.com/rs/zerolog"

	utilRes "campaign-pool-be/utils/response"
	utilVal "campaign-pool-be/utils/validator"
)

type ebookPurchasesController struct {
	purchaseService service.EbookPurchasesService
	usersRepo       usersRepository.UsersRepository
	Log             zerolog.Logger
}

type EbookPurchasesController interface {
	GetByBuyerId(c *fiber.Ctx) error
	PurchaseEbook(c *fiber.Ctx) error
	UpdatePaymentStatus(c *fiber.Ctx) error
	GetPurchaseById(c *fiber.Ctx) error
	ConfirmPayment(c *fiber.Ctx) error
}

func NewEbookPurchasesController(purchaseService service.EbookPurchasesService, usersRepo usersRepository.UsersRepository, log zerolog.Logger) EbookPurchasesController {
	return &ebookPurchasesController{
		purchaseService: purchaseService,
		usersRepo:       usersRepo,
		Log:             log,
	}
}

// GetByBuyerId Purchase
// @Summary      Get user purchases
// @Description  API for getting user purchases
// @Tags         Ebook Purchase
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param 	     req query paginator.Pagination false "pagination parameters"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ebooks/purchases [get]
func (_i *ebookPurchasesController) GetByBuyerId(c *fiber.Ctx) error {
	paginate, err := paginator.Paginate(c)
	if err != nil {
		return err
	}

	authToken := c.Get("Authorization")

	purchasesData, paging, err := _i.purchaseService.GetByBuyerId(authToken, paginate)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Purchases successfully retrieved"},
		Data:     purchasesData,
		Meta:     paging,
	})
}

// PurchaseEbook Purchase
// @Summary      Purchase ebook
// @Description  API for purchasing ebook
// @Tags         Ebook Purchase
// @Security     Bearer
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        ebookId path int true "Ebook ID"
// @Param        paymentMethod query string true "Payment Method"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ebooks/purchase/{ebookId} [post]
func (_i *ebookPurchasesController) PurchaseEbook(c *fiber.Ctx) error {
	ebookId, err := strconv.ParseUint(c.Params("ebookId"), 10, 0)
	if err != nil {
		return err
	}

	paymentMethod := c.Query("paymentMethod")
	if paymentMethod == "" {
		return utilRes.Resp(c, utilRes.Response{
			Success:  false,
			Messages: utilRes.Messages{"Payment method is required"},
		})
	}

	authToken := c.Get("Authorization")

	purchase, err := _i.purchaseService.PurchaseEbook(authToken, uint(ebookId), paymentMethod)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Ebook purchase successfully created"},
		Data:     purchase,
	})
}

// UpdatePaymentStatus Purchase
// @Summary      Update payment status
// @Description  API for updating payment status
// @Tags         Ebook Purchase
// @Security     Bearer
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        id path int true "Purchase ID"
// @Param 	     payload body PaymentStatusUpdateRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ebooks/purchases/{id}/payment [put]
func (_i *ebookPurchasesController) UpdatePaymentStatus(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	req := new(PaymentStatusUpdateRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	err = _i.purchaseService.UpdatePaymentStatus(uint(id), req.PaymentStatus, req.TransactionId, req.PaymentProof)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Payment status successfully updated"},
	})
}

// GetPurchaseById Purchase
// @Summary      Get purchase by ID
// @Description  API for getting purchase by ID
// @Tags         Ebook Purchase
// @Security     Bearer
// @Param        id path int true "Purchase ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ebooks/purchases/{id} [get]
func (_i *ebookPurchasesController) GetPurchaseById(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	purchaseData, err := _i.purchaseService.GetPurchaseById(uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Purchase successfully retrieved"},
		Data:     purchaseData,
	})
}

// ConfirmPayment Purchase
// @Summary      Confirm payment
// @Description  API for confirming payment
// @Tags         Ebook Purchase
// @Security     Bearer
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        id path int true "Purchase ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ebooks/purchases/{id}/confirm [put]
func (_i *ebookPurchasesController) ConfirmPayment(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	err = _i.purchaseService.ConfirmPayment(uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Payment successfully confirmed"},
	})
}

// PaymentStatusUpdateRequest struct for payment status update
type PaymentStatusUpdateRequest struct {
	PaymentStatus string `json:"paymentStatus" validate:"required"`
	TransactionId string `json:"transactionId"`
	PaymentProof  string `json:"paymentProof"`
}
