package admin

import (
	"fmt"

	"quyun/app/models"
	"quyun/app/requests"
	"quyun/database/fields"
	"quyun/providers/wepay"

	"github.com/gofiber/fiber/v3"
	"github.com/pkg/errors"
)

type OrderListQuery struct {
	OrderNumber *string `query:"order_number"`
	UserID      *int64  `query:"user_id"`
}

// @provider
type orders struct {
	wepay *wepay.Client
}

// List users
//
//	@Router	/admin/orders [get]
//	@Bind	pagination query
//	@Bind	query query
func (ctl *orders) List(ctx fiber.Ctx, pagination *requests.Pagination, query *OrderListQuery) (*requests.Pager, error) {
	cond := models.Orders.BuildConditionWithKey(query.OrderNumber, query.UserID)
	return models.Orders.List(ctx.Context(), pagination, cond)
}

// Refund
// @Router	/admin/orders/:id/refund [post]
// @Bind	id path
func (ctl *orders) Refund(ctx fiber.Ctx, id int64) error {
	order, err := models.Orders.GetByID(ctx.Context(), id)
	if err != nil {
		return err
	}

	post, err := models.Posts.GetByID(ctx.Context(), order.PostID)
	if err != nil {
		return err
	}

	if order.PaymentMethod == "balance" {
		if err := models.Users.AddBalance(ctx.Context(), order.UserID, order.Meta.Data.CostBalance); err != nil {
			return errors.Wrap(err, "add balance failed")
		}

		if err := models.Users.RevokePosts(ctx.Context(), order.UserID, order.PostID); err != nil {
			return errors.Wrap(err, "revoke posts failed")
		}

		order.Status = fields.OrderStatusRefundSuccess
		if err := models.Orders.Update(ctx.Context(), order); err != nil {
			return errors.Wrap(err, "update order failed")
		}

		return nil
	}

	refundTotal := order.Price*int64(order.Discount)/100 - order.Meta.Data.CostBalance
	resp, err := ctl.wepay.Refund(ctx.Context(), func(bm *wepay.BodyMap) {
		bm.
			OutRefundNo(order.OrderNo).
			OutTradeNo(order.OrderNo).
			TransactionID(order.TransactionID).
			CNYRefundAmount(refundTotal, refundTotal).
			RefundReason(fmt.Sprintf("%s 退款", post.Title))
	})
	if err != nil {
		return err
	}

	meta := order.Meta.Data
	meta.RefundResp = resp
	order.Meta = fields.ToJson(meta)
	order.RefundTransactionID = resp.RefundId
	order.Status = fields.OrderStatusRefundProcessing

	if err := models.Orders.Update(ctx.Context(), order); err != nil {
		return err
	}

	return nil
}
