package com.yueqian.xingyun.sc.vo.retail.out;

import com.lframework.starter.common.exceptions.impl.DefaultClientException;
import com.lframework.starter.common.exceptions.impl.InputErrorException;
import com.lframework.starter.common.utils.CollectionUtil;
import com.lframework.starter.common.utils.NumberUtil;
import com.lframework.starter.common.utils.StringUtil;
import com.lframework.starter.web.core.utils.ApplicationUtil;
import com.lframework.starter.web.core.vo.BaseVo;
import com.yueqian.xingyun.sc.dto.purchase.receive.GetPaymentDateDto;
import com.yueqian.xingyun.sc.entity.RetailConfig;
import com.yueqian.xingyun.sc.service.retail.RetailConfigService;
import com.yueqian.xingyun.sc.service.retail.RetailOutSheetService;
import com.yueqian.xingyun.sc.vo.paytype.OrderPayTypeVo;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;

@Data
public class CreateRetailOutSheetVo implements BaseVo, Serializable {

  private static final long serialVersionUID = 1L;

  /**
   * 仓库ID
   */
  @Schema(description = "仓库ID", requiredMode = Schema.RequiredMode.REQUIRED)
  @NotBlank(message = "仓库ID不能为空！")
  private String scId;

  /**
   * 会员ID
   */
  @Schema(description = "会员ID")
  private String memberId;

  /**
   * 销售员ID
   */
  @Schema(description = "销售员ID")
  private String salerId;

  /**
   * 付款日期
   */
  @Schema(description = "付款日期")
  private LocalDate paymentDate;

  /**
   * 是否允许修改付款日期
   */
  @Schema(description = "是否允许修改付款日期")
  private Boolean allowModifyPaymentDate = Boolean.FALSE;

  /**
   * 商品信息
   */
  @Schema(description = "商品信息", requiredMode = Schema.RequiredMode.REQUIRED)
  @Valid
  @NotEmpty(message = "商品不能为空！")
  private List<RetailOutProductVo> products;

  /**
   * 支付方式
   */
  @Schema(description = "支付方式")
  @Valid
  private List<OrderPayTypeVo> payTypes;

  /**
   * 备注
   */
  @Schema(description = "备注")
  private String description;

  public void validate() {

    RetailConfigService retailConfigService = ApplicationUtil.getBean(RetailConfigService.class);
    RetailConfig config = retailConfigService.get();
    if (config.getRetailOutSheetRequireMember()) {
      if (StringUtil.isBlank(this.memberId)) {
        throw new DefaultClientException("请选择会员！");
      }
    }

    RetailOutSheetService retailOutSheetService = ApplicationUtil.getBean(
        RetailOutSheetService.class);
    GetPaymentDateDto paymentDate = retailOutSheetService.getPaymentDate(this.getMemberId());
    if (paymentDate.getAllowModify()) {
      if (this.getPaymentDate() == null) {
        throw new InputErrorException("付款日期不能为空！");
      }
    }

    int orderNo = 1;
    for (RetailOutProductVo product : this.products) {

      if (StringUtil.isBlank(product.getProductId())) {
        throw new InputErrorException("第" + orderNo + "行商品不能为空！");
      }

      if (product.getOrderNum() == null) {
        throw new InputErrorException("第" + orderNo + "行商品零售数量不能为空！");
      }

      if (NumberUtil.le(product.getOrderNum(), BigDecimal.ZERO)) {
        throw new InputErrorException("第" + orderNo + "行商品零售数量必须大于0！");
      }

      if (!NumberUtil.isNumberPrecision(product.getOrderNum(), 8)) {
        throw new InputErrorException("第" + orderNo + "行商品零售数量最多允许8位小数！");
      }

      if (product.getOriPrice() == null) {
        throw new InputErrorException("第" + orderNo + "行商品参考零售价不能为空！");
      }

      if (product.getTaxPrice() == null) {
        throw new InputErrorException("第" + orderNo + "行商品价格不能为空！");
      }

      if (NumberUtil.lt(product.getTaxPrice(), 0D)) {
        throw new InputErrorException("第" + orderNo + "行商品价格不允许小于0！");
      }

      if (!NumberUtil.isNumberPrecision(product.getTaxPrice(), 6)) {
        throw new InputErrorException("第" + orderNo + "行商品价格最多允许6位小数！");
      }

      if (!NumberUtil.equal(product.getOriPrice(), 0D)) {
        // 由 根据原价和折扣率校验现价 更改为 根据原价、现价计算折扣率，即：不以传入的折扣率为准
        BigDecimal discountRate = NumberUtil.getNumber(
            NumberUtil.mul(NumberUtil.div(product.getTaxPrice(), product.getOriPrice()), 100), 2);
        product.setDiscountRate(discountRate);
      } else {
        //如果原价为0，折扣率固定为100
        product.setDiscountRate(BigDecimal.valueOf(100));
      }

      orderNo++;
    }

    BigDecimal totalAmount = this.products.stream()
        .map(t -> NumberUtil.getNumber(NumberUtil.mul(t.getOrderNum(), t.getTaxPrice()), 2)).reduce(NumberUtil::add)
        .orElse(BigDecimal.ZERO);
    BigDecimal payTypeAmount = CollectionUtil.isEmpty(this.payTypes) ? BigDecimal.ZERO
        : this.payTypes.stream().map(OrderPayTypeVo::getPayAmount).reduce(NumberUtil::add)
            .orElse(BigDecimal.ZERO);
    if (!NumberUtil.equal(totalAmount, payTypeAmount)) {
      throw new InputErrorException("所有支付方式的支付金额不等于含税总金额，请检查！");
    }
  }
}
