// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2

package order

import (
	"context"
	"encoding/json"
	"errors"
	"strconv"
	"time"

	"juwan-backend/app/order/rpc/orderservice"
	"juwan-backend/app/player/rpc/playerservice"
	"juwan-backend/common/utils/contextj"

	"juwan-backend/app/order/api/internal/svc"
	"juwan-backend/app/order/api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type CreateOrderLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// 创建订单
func NewCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateOrderLogic {
	return &CreateOrderLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *CreateOrderLogic) CreateOrder(req *types.CreateOrderReq) (resp *types.CreateOrderResp, err error) {
	if req.Quantity <= 0 {
		return nil, errors.New("quantity must be greater than 0")
	}

	consumerID, err := contextj.UserIDFrom(l.ctx)
	if err != nil {
		return nil, err
	}

	serviceResp, err := l.svcCtx.PlayerRpc.GetPlayerServicesById(l.ctx, &playerservice.GetPlayerServicesByIdReq{Id: req.ServiceId})
	if err != nil {
		return nil, err
	}
	service := serviceResp.GetPlayerServices()
	if service == nil {
		return nil, errors.New("player service not found")
	}

	if req.PlayerId > 0 && service.GetPlayerId() != req.PlayerId {
		return nil, errors.New("service does not belong to player")
	}

	playerID := service.GetPlayerId()
	if req.PlayerId > 0 {
		playerID = req.PlayerId
	}

	price := service.GetPrice()
	totalPrice := price * float64(req.Quantity)
	totalPriceStr := strconv.FormatFloat(totalPrice, 'f', 2, 64)

	serviceSnapshot := types.PlayerService{
		Id:           req.ServiceId,
		PlayerId:     playerID,
		GameId:       service.GetGameId(),
		Title:        service.GetTitle(),
		Description:  service.GetDescription(),
		Price:        price,
		Unit:         service.GetUnit(),
		RankRange:    service.GetRankRange(),
		Availability: service.GetAvailability(),
	}
	snapshotBytes, err := json.Marshal(serviceSnapshot)
	if err != nil {
		return nil, err
	}

	now := time.Now().Unix()
	status := "pending_payment"

	addReq := &orderservice.AddOrdersReq{
		ConsumerId:      consumerID,
		PlayerId:        playerID,
		ServiceSnapshot: string(snapshotBytes),
		Status:          &status,
		TotalPrice:      totalPriceStr,
		CreatedAt:       &now,
		UpdatedAt:       &now,
	}
	if req.ShopId > 0 {
		addReq.ShopId = &req.ShopId
	}
	if req.Note != "" {
		addReq.Note = &req.Note
	}

	addResp, err := l.svcCtx.OrderRpc.AddOrders(l.ctx, addReq)
	if err != nil {
		return nil, err
	}

	created, err := l.svcCtx.OrderRpc.GetOrdersById(l.ctx, &orderservice.GetOrdersByIdReq{Id: addResp.Id})
	if err != nil {
		return nil, err
	}

	return &types.CreateOrderResp{Ok: true, Order: toAPIOrder(created.GetOrders())}, nil
}
