package com.jeequan.jeepay.core.model.rqrs.payorder;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.rqrs.AbstractMchAppRQ;
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.*;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.BeanUtils;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/*
* 创建订单请求参数对象
* 聚合支付接口（统一下单）
*
* @author terrfly
*
* @date 2021/6/8 17:33
*/
@Data
@Accessors(chain = true)
public class UnifiedOrderRQ extends AbstractMchAppRQ {

    public static final Integer DEFAULT_LIMIT_PAY = -1;

    /** 商户订单号 **/
    @NotBlank(message="商户订单号不能为空")
    private String mchOrderNo;

    /** 支付方式  如： wxpay_jsapi,alipay_wap等   **/
    @NotBlank(message="支付方式不能为空")
    private String wayCode;

    /** 支付金额， 单位：分 **/
    @NotNull(message="支付金额不能为空")
    @Min(value = 1, message = "支付金额不能为空")
    private Long amount;

    /** 货币代码 **/
    @NotBlank(message="货币代码不能为空")
    private String currency;

    /** 客户端IP地址 **/
    private String clientIp;

    /** 商品标题 **/
    @NotBlank(message="商品标题不能为空")
    private String subject;

    /** 商品描述信息 **/
    @NotBlank(message="商品描述信息不能为空")
    private String body;

    /** 商户的门店ID **/
    private String storeId;

    /** 门店收银员ID **/
    private Long storeUserId;

    /** 设备信息 **/
    private String deviceInfo;

    /** 商户的码牌ID **/
    private Long qrcId;

    /** 异步通知地址 **/
    private String notifyUrl;

    /** 跳转通知地址 **/
    private String returnUrl;

    /** 卖家备注 **/
    private String sellerRemark;

    /** 买家备注 **/
    private String buyerRemark;

    /** 订单失效时间, 单位：秒 **/
    private Integer expiredTime;

    /** 终端编号（商户自行录入的 trmNo 字段 ） **/
    private String mchTrmNo;

    /** 特定渠道发起额外参数 **/
    private String channelExtra;

    /** 商户扩展参数 **/
    private String extParam;

    /** 分账模式： 0-该笔订单不允许分账, 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额) **/
    @Range(min = 0, max = 2, message = "分账模式设置值有误")
    private Byte divisionMode;

    /** 渠道特殊业务数据 **/
    private String channelBizData;

    /** 会员ID **/
    private String mbrId;

    /** 会员手机号 **/
    private String mbrTel;

    /**
     * 是否禁用信用卡 -1：不禁用 1：禁用 不传标识不禁用
     */
    private Integer limitPay;

    /**
     * 暂时只支持扫码支付
     * 扫码类型 0或不填：扫码支付 1：支付宝刷脸支付；2: 微信刷脸支付
     */
    private Integer scanType;

    /**
     * 花呗分期参数 取值 3 6 12 期
     */
    private Integer hbFqNum;

    /**
     * 卖家承担手续费比例 支付宝花呗分期必送字段: 卖家承担手续费比例，间连模式下只支持传0。
     */
    private Integer hbFqPercent;

    /**
     * 优惠对象
     */
    private JSONObject discount;

    /**
     * 红包营销规则
     */
    private Boolean isMarketRed;

    /**
     * 是否校验小程序参数
     */
    @JSONField(serialize = false)
    private Boolean isAppletCheck = false;

    /**
     * 是否请求渠道
     */
    @JSONField(serialize = false)
    private Boolean isReqChannel = true;

    /**
     * 是否来源路由
     */
    @JSONField(serialize = false)
    private Boolean isRoute = false;

    @JSONField(serialize = false)
    private String tk;

    /**
     * 路由编号
     */
    @JSONField(serialize = false)
    private String routeNo;



    /** 返回真实的bizRQ **/
    public UnifiedOrderRQ buildBizRQ(){
        if(CS.PAY_WAY_CODE.ALI_BAR.equals(wayCode)){
            AliBarOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), AliBarOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.ALI_JSAPI.equals(wayCode)){
            AliJsapiOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), AliJsapiOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.ALI_LITE.equals(wayCode)){
            AliLiteOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), AliLiteOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.QR_CASHIER.equals(wayCode)){
            this.isReqChannel = false;
            QrCashierOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), QrCashierOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.WEB_CASHIER.equals(wayCode)){
            this.isReqChannel = false;
            WebCashierOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), WebCashierOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.WX_JSAPI.equals(wayCode)){
            WxJsapiOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), WxJsapiOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.WX_APP.equals(wayCode)){
            WxAppOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), WxAppOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.WX_LITE.equals(wayCode)){
            WxLiteOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), WxLiteOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.WX_BAR.equals(wayCode)){
            WxBarOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), WxBarOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.WX_NATIVE.equals(wayCode)){
            WxNativeOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), WxNativeOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.WX_H5.equals(wayCode)){
            WxH5OrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), WxH5OrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.YSF_BAR.equals(wayCode)){
            YsfBarOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), YsfBarOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.YSF_JSAPI.equals(wayCode)){
            this.isReqChannel = true;
            YsfJsapiOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), YsfJsapiOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.AUTO_BAR.equals(wayCode)){
            AutoBarOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), AutoBarOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.ALI_APP.equals(wayCode)){
            AliAppOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), AliAppOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.ALI_WAP.equals(wayCode)){
            AliWapOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), AliWapOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.ALI_PC.equals(wayCode)){
            this.isReqChannel = true;
            AliPcOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), AliPcOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.ALI_QR.equals(wayCode)){
            AliQrOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), AliQrOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.UP_APP.equals(wayCode)){
            UpAppOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), UpAppOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.UP_WAP.equals(wayCode)){
            UpWapOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), UpWapOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.UP_QR.equals(wayCode)){
            UpQrOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), UpQrOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.UP_BAR.equals(wayCode)){
            UpBarOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), UpBarOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.UP_B2B.equals(wayCode)){
            UpB2bOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), UpB2bOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.UP_PC.equals(wayCode)){
            UpPcOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), UpPcOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if (CS.PAY_WAY_CODE.PP_PC.equals(wayCode)){
            PPPcOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), PPPcOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.SAND_H5.equals(wayCode)){
            SandH5OrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), SandH5OrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.AUTO_POS.equals(wayCode)){
            AutoPosOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelBizData, "{}"), AutoPosOrderRQ.class);

            AutoPosOrderRQ autoPosOrderRQ = AutoPosOrderRQ.getDefaultAutoPosOrderRQ();
            BeanUtil.copyProperties(bizRQ, autoPosOrderRQ, CopyOptions.create().setIgnoreNullValue(true));

            BeanUtils.copyProperties(this, autoPosOrderRQ);
            return autoPosOrderRQ;
        }else if(CS.PAY_WAY_CODE.CASHIER.equals(wayCode)){
            ChannelCashierOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), ChannelCashierOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.BANK_QUICK.equals(wayCode)){
            BankQuickOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), BankQuickOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.BANK_B2C.equals(wayCode)){
            BankB2cOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), BankB2cOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.DCEP_BAR.equals(wayCode)){
            DcepBarOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), DcepBarOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }else if(CS.PAY_WAY_CODE.DCEP_QR.equals(wayCode)){
            DcepQrOrderRQ bizRQ = JSONObject.parseObject(StringUtils.defaultIfEmpty(this.channelExtra, "{}"), DcepQrOrderRQ.class);
            BeanUtils.copyProperties(this, bizRQ);
            return bizRQ;
        }

        return this;
    }

    /** 获取渠道用户ID **/
    @JSONField(serialize = false)
    public String getChannelUserId(){
        return null;
    }


    @Data
    public static class DeviceInfo {

        /** 设备类型：qr_code-码牌，qr_box_kxp 扫码客显屏音箱 scan_pos-扫码POS，auto_pos-智能POS，other-其他 **/
        private String deviceType;

        /** 设备号 **/
        private String deviceNo;

        /** 设备厂商 （智能POS厂商即为 ifCode，扫码POS仅商户系统调用，已通过cahnnelBizData传值） **/
        private String provider;

    }

    @Override
    public String apiName() {
        return CS.MCH_APP_API_ENUM.API_PAY_ORDER;
    }
}
