package com.starry.admin.modules.order.service.impl;

import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.order.module.constant.OrderConstant;
import com.starry.admin.modules.order.module.dto.OrderAmountBreakdown;
import com.starry.admin.modules.order.module.dto.OrderCreationContext;
import com.starry.admin.modules.order.module.dto.OrderPlacementCommand;
import com.starry.admin.modules.order.module.dto.PaymentInfo;

class ServiceOrderPlacementStrategy extends AbstractOrderPlacementStrategy {

    private final OrderConstant.PlaceType placeType;

    ServiceOrderPlacementStrategy(OrderLifecycleServiceImpl service, OrderConstant.PlaceType placeType) {
        super(service);
        this.placeType = placeType;
    }

    @Override
    protected OrderAmountBreakdown handlePricing(OrderPlacementCommand command, OrderCreationContext context) {
        if (context.getPlaceType() != placeType) {
            throw new CustomException("下单类型与服务计价策略不匹配");
        }

        OrderPlacementCommand.PricingInput pricingInput = command.getPricingInput();
        if (pricingInput == null) {
            PaymentInfo info = context.getPaymentInfo();
            if (info == null) {
                throw new CustomException("支付信息不能为空");
            }
            PaymentInfo normalized = PaymentInfo.builder()
                    .orderMoney(service.normalizeMoney(info.getOrderMoney()))
                    .discountAmount(service.normalizeMoney(info.getDiscountAmount()))
                    .finalAmount(service.normalizeMoney(info.getFinalAmount()))
                    .couponIds(info.getCouponIds())
                    .payMethod(info.getPayMethod())
                    .build();
            context.setPaymentInfo(normalized);
            return service.fallbackBreakdown(normalized);
        }
        if (pricingInput.getPlaceType() != placeType) {
            throw new CustomException("计价参数的下单类型不匹配");
        }

        OrderAmountBreakdown breakdown = service.calculateOrderAmounts(pricingInput);
        PaymentInfo currentInfo = context.getPaymentInfo();
        PaymentInfo updated = PaymentInfo.builder()
                .orderMoney(breakdown.getGrossAmount())
                .discountAmount(breakdown.getDiscountAmount())
                .finalAmount(breakdown.getNetAmount())
                .couponIds(pricingInput.getCouponIds())
                .payMethod(currentInfo != null ? currentInfo.getPayMethod() : null)
                .build();
        context.setPaymentInfo(updated);
        return breakdown;
    }
}
