package cn.iocoder.yudao.module.order.vo.orderException;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.i18n.core.I18nMessage;
import cn.iocoder.yudao.module.order.dto.OrderRemindExceptionDto;
import cn.iocoder.yudao.module.order.enums.OrderAbnormalStateEnum;
import cn.iocoder.yudao.module.order.enums.OrderStatusEnum;
import cn.iocoder.yudao.module.order.enums.OrderStatusMsgEnum;
import cn.iocoder.yudao.module.order.vo.order.GuanLianOrderStatusVO;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 订单异常 Response VO
 *
 * @author 系统管理员
 */
@Data
@ApiModel("管理后台 - 订单分页异常 Response VO")
@Slf4j
public class OrderBackVO {

    @ExcelProperty("主键ID")
    @ApiModelProperty(value = "主键ID")
    private Long id;

    @ExcelProperty("订单id")
    @ApiModelProperty(value = "订单id")
    private Long orderId;

    @ExcelProperty("订单号")
    @ApiModelProperty(value = "订单号")
    private String orderNo;

    @ExcelProperty("特需,多个,号分割,根据数据字典取值")
    @ApiModelProperty(value = "特需")
    private String specialNeed;

    @ExcelProperty("唛头")
    @ApiModelProperty(value = "唛头")
    private String marks;

    @ExcelProperty("填单总箱数(返回是一个JSON，需要取JSON的)")
    @ApiModelProperty(value = "填单总箱数")
    private String totalBox;

    @ExcelProperty("入仓箱数")
    @ApiModelProperty(value = "入仓箱数")
    private String warehousingBox;

    @ExcelProperty("填单体积")
    @ApiModelProperty(value = "填单体积")
    private BigDecimal totalVolume;

    @ExcelProperty("入仓体积")
    @ApiModelProperty(value = "入仓体积")
    private BigDecimal volume;

    @ExcelProperty("填单重量")
    @ApiModelProperty(value = "填单重量")
    private BigDecimal totalWeight;

    @ExcelProperty("入仓重量")
    @ApiModelProperty(value = "入仓重量")
    private BigDecimal weight;

    @ApiModelProperty(value = "重货方数")
    private BigDecimal wVolume;

    @ApiModelProperty(value = "泡货体积")
    private BigDecimal vWeight;

    @ExcelProperty("是否控货")
    @ApiModelProperty(value = "是否控货")
    private Boolean isCargoControl;

    @ExcelProperty("运输方式id")
    @ApiModelProperty(value = "运输方式id")
    private Integer transportId;

    @ApiModelProperty(value = "目的地中文")
    private String destinationZh;

    @ApiModelProperty(value = "目的地英文")
    private String destinationEn;

    @ExcelProperty(value = "订单状态详情见字典：order_status")
    @ApiModelProperty(value = "订单状态详情见字典：order_status")
    private Integer status;

    @ExcelProperty("异常状态")
    @ApiModelProperty(value = "异常状态  订单状态详情见字典：order_exception_status")
    private Integer orderExceptionStatus;

    @ExcelProperty("异常类型")
    @ApiModelProperty(value = "异常类型  订单状态详情见字典：order_error_type")
    private String orderExceptionType;

    @ExcelProperty("异常描述")
    @ApiModelProperty(value = "异常描述 异常描述JSON")
    private String orderExceptionRemark;

    @ExcelProperty("异常详情")
    @ApiModelProperty(value = "异常详情")
    private String orderExceptionDetails;

    @ExcelProperty("异常备注")
    @ApiModelProperty(value = "异常备注")
    private String orderExceptionNotes;
    @ExcelProperty("异常描述-带中英文")
    @ApiModelProperty(value = "异常描述-带中英文")
    private OrderExceptionDescVO orderExceptionDescVO;

    @ApiModelProperty(value = "报关方式")
    private Integer customsType;

    @ApiModelProperty(value = "是否多个异常")
    private Boolean moreException;

    @ApiModelProperty(value = "全部异常类型,号分隔")
    private String allExceptionType;

    @ApiModelProperty(value = "订单类型")
    private Integer orderType;
    @ApiModelProperty(value = "订单状态")
    private String statusMsg;
    @ApiModelProperty(value = "语言")
    private Integer lang;

    @ApiModelProperty(value = "不阻塞流程的异常说明(支持多个异常说明)")
    private String exceptionReason;

    @ApiModelProperty(value = "不阻塞流程的异常说明(支持多个异常说明)")
    private List<OrderRemindExceptionDto> remindExceptionDtoList;

    @ApiModelProperty(value = "端口(默认管理端)")
    private Integer userType = 2;

    @ApiModelProperty(value = "审核类型(字典 order_approval_type) 0 为正常")
    private Integer auditType;

    @ExcelProperty("审核结果")
    @ApiModelProperty(value = "审核结果")
    private String auditResult;

    @ExcelProperty("订单异常状态")
    @ApiModelProperty(value = "订单异常状态(字典 order_abnormal_state)")
    private Integer abnormalState;

    @ExcelProperty("订单入仓状态")
    @ApiModelProperty(value = "订单入仓状态(字典 order_warehouse_in_status)")
    private Integer inWarehouseState;


    @ExcelProperty("提货状态")
    @ApiModelProperty(value = "提货状态：0 未提货 1 部分提货 2 已提货")
    private Integer pickState;

    @ExcelProperty("订单出货状态")
    @ApiModelProperty(value = "订单出货状态(字典 order_shipment_state)")
    private Integer shipmentState;

    @ApiModelProperty(value = "空运可出货状态： 0 默认值 1 待出 2 可出 3 备货中 4 已备货")
    private Integer airShipment;

    @ApiModelProperty(value = "关联订单状态")
    private String guanLianOrderStatus;

    @ApiModelProperty(value = "关联订单状态")
    private List<GuanLianOrderStatusVO> guanLianOrderStatusVOList;


    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo.contains("DRAFT") ? null : orderNo;
    }

    public void setStatus(Integer status) {
        this.status = status;
        this.getOrderDesc();

    }

    public void setAbnormalState(Integer abnormalState) {
        this.abnormalState = abnormalState;
        this.getOrderDesc();
    }

    public void setInWarehouseState(Integer inWarehouseState) {
        this.inWarehouseState = inWarehouseState;
        this.getOrderDesc();
    }

    public void setAirShipment(Integer airShipment) {
        this.airShipment = airShipment;
        this.getOrderDesc();
    }

    public void setShipmentState(Integer shipmentState) {
        this.shipmentState = shipmentState;
        this.getOrderDesc();
    }

    public void setPickState(Integer pickState) {
        this.pickState = pickState;
        if (Objects.nonNull(pickState) && pickState > 0) {
            // 当提货状态不未空时，判断提货状态是否需要转化为对应的原有主状态中的提货状态
            this.status = pickState == 1 ? 21 : 20;
        }
        this.getOrderDesc();
    }

    public void setAuditType(Integer auditType) {
        this.auditType = auditType;
        this.getOrderDesc();
    }

    public void setAuditResult(String auditResult) {
        this.auditResult = auditResult;
        this.getOrderDesc();

    }

    public void setOrderExceptionDescVO() {
        this.orderExceptionDescVO = JSONObject.parseObject(this.orderExceptionRemark, OrderExceptionDescVO.class);
    }

    public OrderExceptionDescVO getOrderExceptionDescVO() {
        return JSONObject.parseObject(this.orderExceptionRemark, OrderExceptionDescVO.class);
    }

    public void setGuanLianOrderStatus(String guanLianOrderStatus) {
        this.guanLianOrderStatus = guanLianOrderStatus;
        if (StringUtils.isNotBlank(guanLianOrderStatus)) {
            this.guanLianOrderStatusVOList = JSONObject.parseArray(guanLianOrderStatus, GuanLianOrderStatusVO.class);
            this.getOrderDesc();
        }
    }

    public void setGuanLianOrderStatusVOList(List<GuanLianOrderStatusVO> guanLianOrderStatusVOList) {
        this.guanLianOrderStatusVOList = guanLianOrderStatusVOList;
        if (CollectionUtil.isNotEmpty(guanLianOrderStatusVOList)) {
            this.guanLianOrderStatus = JSONObject.toJSONString(guanLianOrderStatusVOList);
        }
    }


    public void setLang(Integer lang) {
        this.lang = lang;
        if (StringUtils.isNotBlank(this.exceptionReason) && Objects.nonNull(lang)) {
            this.remindExceptionDtoList = JSONObject.parseArray(this.exceptionReason, OrderRemindExceptionDto.class)
                    .stream()
                    .peek(ern -> ern.setReason(lang == 0 ? I18nMessage.getZhMessage(ern.getReason()) : I18nMessage.getEnMessage(ern.getReason())))
                    .collect(Collectors.toList());
        }
        this.getOrderDesc();
    }

    public void setExceptionReason(String exceptionReason) {
        this.exceptionReason = exceptionReason;
        if (StringUtils.isNotBlank(exceptionReason) && Objects.nonNull(this.lang)) {
            this.remindExceptionDtoList = JSONObject.parseArray(exceptionReason, OrderRemindExceptionDto.class)
                    .stream()
                    .peek(ern -> ern.setReason(lang == 0 ? I18nMessage.getZhMessage(ern.getReason()) : I18nMessage.getEnMessage(ern.getReason())))
                    .collect(Collectors.toList());
        }
        this.getOrderDesc();
    }

    private void getOrderDesc() {
        // TODO 这里的文案国际化现在只支持两种语言，如果需要支持更多的语言，需要优化
        Integer lang = Objects.nonNull(this.lang) ? this.lang : I18nMessage.getLang();
        if (null != this.status && this.status.equals(OrderStatusEnum.CANCEL.getValue()) && this.userType != null) {

            String message = this.userType == 2 ? OrderStatusMsgEnum.CANCEL.getAdminSourceName() : OrderStatusMsgEnum.CANCEL.getCustomerSourceName();
            this.statusMsg = lang == 0 ? I18nMessage.getZhMessage(message) : I18nMessage.getEnMessage(message);
        } else if (null != this.abnormalState && this.abnormalState > 0) {

            OrderAbnormalStateEnum abnormalStateEnum = OrderAbnormalStateEnum.valueOf(abnormalState);
            if (Objects.isNull(abnormalStateEnum)) {
                this.statusMsg = lang == 0 ? "未知异常" : "UNKNOWN_EXCEPTION";
            } else {
                this.statusMsg = lang == 0 ? I18nMessage.getZhMessage(abnormalStateEnum.getDesc()) : I18nMessage.getEnMessage(abnormalStateEnum.getDesc());
            }
        } else if (StringUtils.isNotBlank(this.auditResult)) {

            this.statusMsg = lang == 0 ? I18nMessage.getZhMessage(auditResult) : I18nMessage.getEnMessage(auditResult);
        } else if (CollectionUtil.isNotEmpty(this.remindExceptionDtoList) && this.remindExceptionDtoList.size() > 0) {

            this.statusMsg = remindExceptionDtoList.get(0).getReason();
        } else if (null != this.status && this.status == 5 && CollectionUtil.isNotEmpty(this.guanLianOrderStatusVOList)) {

            // 已入仓的订单才展示关联异常信息
            // 如果查询返回了关联订单状态，表示需要显示关联订单状态，关联订单状态冗余的是国际化key值
            // 排序
            this.guanLianOrderStatusVOList = this.guanLianOrderStatusVOList.stream().sorted(Comparator.comparing(GuanLianOrderStatusVO::getType)).collect(Collectors.toList());
            GuanLianOrderStatusVO guanlianOrderStatusVO = guanLianOrderStatusVOList.get(0);
            switch (guanlianOrderStatusVO.getType()) {
                case 1:
                    // 关联异常状态封装，订单状态显示“关联单#订单号#，#异常名称#”Associated order %s, %s
                    String abnormalMsg = lang == 0 ? I18nMessage.getZhMessage("guanlian.order.abnormalState") : I18nMessage.getEnMessage("guanlian.order.abnormalState");
                    this.statusMsg = String.format(abnormalMsg, guanlianOrderStatusVO.getOrderNo(), I18nMessage.getMessage(guanlianOrderStatusVO.getStatusMsg()));
                    break;
                case 2:
                    // 关联审批状态封装，订单状态显示“关联单#订单号##审核状态#”
                    String auditMsg = lang == 0 ? I18nMessage.getZhMessage("guanlian.order.audit") : I18nMessage.getEnMessage("guanlian.order.audit");
                    this.statusMsg = String.format(auditMsg, guanlianOrderStatusVO.getOrderNo(), I18nMessage.getMessage(guanlianOrderStatusVO.getStatusMsg()));
                    break;
                case 3:
                    // 关联未入仓状态封装，订单状态显示“关联单#订单号#未入仓”
                    String waitWarehouseInMsg = lang == 0 ? I18nMessage.getZhMessage(guanlianOrderStatusVO.getStatusMsg()) : I18nMessage.getEnMessage(guanlianOrderStatusVO.getStatusMsg());
                    this.statusMsg = String.format(waitWarehouseInMsg, guanlianOrderStatusVO.getOrderNo());
                    break;
                default:
                    this.statusMsg = lang == 0 ? I18nMessage.getZhMessage(guanlianOrderStatusVO.getStatusMsg()) : I18nMessage.getEnMessage(guanlianOrderStatusVO.getStatusMsg());
            }
        } else if (null != this.status && null != this.inWarehouseState && null != this.shipmentState && null != this.airShipment && null != this.transportId) {

            this.statusMsg = OrderStatusMsgEnum.getMsg(this.pickState, this.status, this.inWarehouseState, this.shipmentState, this.airShipment, this.transportId, this.userType, lang);
//            this.statusKey = OrderStatusMsgEnum.getStatusKey(this.status, this.inWarehouseState, this.shipmentState);
        }


    }


}
