package com.zhongshu.card.server.core.domain.payment;

import cn.hutool.json.JSONObject;
import com.github.microservice.models.type.OrderFromType;
import com.github.microservice.pay.client.model.ledger.TransactionLogModel;
import com.github.microservice.types.OrderModeType;
import com.github.microservice.types.OrderState;
import com.github.microservice.types.payment.PaymentDeviceType;
import com.github.microservice.types.payment.PaymentType;
import com.zhongshu.card.client.model.school.AreaSimpleModel;
import com.zhongshu.card.client.type.RefundState;
import com.zhongshu.card.client.type.payment.SettlementState;
import com.zhongshu.card.client.utils.DateUtils;
import com.zhongshu.card.server.core.domain.base.SuperMain;
import com.zhongshu.card.server.core.domain.org.UserAccount;
import com.zhongshu.card.server.core.domain.school.CardInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.checkerframework.common.aliasing.qual.NonLeaked;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 消费流水 / 消费订单
 *
 * @author TRX
 * @date 2024/6/17
 */
@Data
@Document
@AllArgsConstructor
@NoArgsConstructor
@NonLeaked
public class ExpenseFlow extends SuperMain {

    //-----------------------------订单信息 start---------------------
    @Indexed(unique = true, sparse = true)
    @Schema(description = "mqtt推送生成的业务数据ID")
    private String mqttDataId;

    private String token;

    @Indexed
    @Schema(description = "订单的总体状态")
    private OrderState orderState;

    @Schema(description = "订单创建类型， 是消费还是查询余额")
    private OrderModeType orderModeType = OrderModeType.Consume;

    @Schema(description = "消费类型，如：餐饮消费、水费、电费 等等")
    private String payType;

    @Indexed
    @Schema(description = "支付方式")
    private PaymentType paymentType;

    //----------------------------消费关联的用户信息 start ----------------------
    @Schema(description = "消费的用户userId")
    private String userId;

    @Schema(description = "用户名称")
    private String userName;

    @Schema(description = "用户信息")
    @DBRef(lazy = true)
    private UserAccount userAccount;

    //-----------------------修复关联的设备信息 start--------------------
    @Schema(description = "消费机设备ID")
    private String deviceId;

    @Schema(description = "设备所属区域信息")
    private AreaSimpleModel area;

    @Schema(description = "所属项目的code")
    private String projectCode;

    @Schema(description = "订单所属的商户")
    private String shopOid;

    //------------------------------消费关联的卡片信息 ---------------------

    @Schema(description = "支付设备和方式")
    private PaymentDeviceType paymentDeviceType;

    @Schema(description = "支付来源：刷卡 二维码 刷脸")
    private OrderFromType orderFromType;

    @Schema(description = "卡片的编号,也是终端刷卡的 卡号")
    private String cardNo = "";

    @Schema(description = "卡片信息")
    private CardInfo cardInfo;

    @Schema(description = "年份，如：2024")
    private Integer year;

    @Schema(description = "月份，如：6")
    private Integer month;

    @Schema(description = "当前月的第几天")
    private Integer dayOfMonth;

    @Schema(description = "今年第几周,如：32")
    private Integer week;

    @Schema(description = "当前年的第几天")
    private Integer dayOfYear;

    @Schema(description = "当前的第几小时")
    private Integer hourOfDay;

    @Schema(description = "消费创建时间 yyyy-MM-dd HH:mm:ss SSS")
    private String paymentTime;

    public void setTimes() {
        this.year = DateUtils.getCurrentYear();
        this.month = DateUtils.getCurrentMonthInYear();
        this.dayOfMonth = DateUtils.getCurrentDayInMonth();
        this.hourOfDay = DateUtils.getCurrentHourOfDay();

        this.dayOfYear = DateUtils.getCurrentDayInYear();
        this.week = DateUtils.getCurrentWeekInYear();
        this.paymentTime = DateUtils.paresTime(System.currentTimeMillis(), DateUtils.patternyyyySSS);
    }

    @Schema(description = "消费订单号")
    private String orderNo;

    @Indexed
    @Schema(description = "支付订单号")
    private String paymentNo;

    @Schema(description = "付款码内容")
    private String qr;

    @Schema(description = "消费金额（单位：分）")
    @Indexed
    private BigDecimal payAmount;

    @Schema(description = "关联信息")
    @Indexed
    private Object param;

    // 交易模式（0:刷卡扣费 1：现金充值2：余额查询 3:钱包转账 4:现金退款）
    private Integer mode = 0;

    //-----------------------订单创建-支付信息 start----------------------

    @Schema(description = "订单是否创建成功")
    private Boolean isCreateSuccess = Boolean.TRUE;

    @Schema(description = "验证参数是否符合要求，可以发起支付")
    private Boolean verifyParamIsSuccess = Boolean.TRUE;

    @Schema(description = "验证参数的提示")
    private String verifyParamMsg;

    /**
     * 设置参数验证错误
     *
     * @param error
     */
    public void setVerifyError(String error) {
        verifyParamIsSuccess = Boolean.FALSE;
        verifyParamMsg = error;
        orderState = OrderState.PARAM_ERROR;
    }

    @Schema(description = "是否必须支付，当是离线的时候，是先在边缘计算，再后面付款，则这个订单用户必须支付")
    private Boolean isMustPay = Boolean.FALSE;

    //------------------支付结果 start-------------------------

    @Schema(description = "失败时的重复次数")
    private Integer repeatTime = 0;

    @Schema(description = "支付订单状态")
    private String paymentStatus;

    @Schema(description = "支付是否成功")
    private Boolean isPaySuccess;

    @Schema(description = "调用支付的 支付结果，保存支付结果返回的以后要使用的参数")
    private JSONObject payResult = new JSONObject();

    @Schema(description = "是否已支付")
    private Boolean isPaid = Boolean.FALSE;

    @Schema(description = "支付结果备注，返回给设备展示")
    private String payRemark;

    @Schema(description = "支付开始时间")
    private Long payStartTime;

    @Schema(description = "支付结束时间")
    private Long payEndTime;

    @Schema(description = "支付耗用的时间")
    private Long payMillis = 0L;

    @Schema(description = "支付账单流水ID集合")
    private List<TransactionLogModel> transactionIds = new ArrayList<TransactionLogModel>();

    //-----------------------退款 start--------------------------

    @Schema(description = "是否退款")
    private Boolean isRefund;

    @Schema(description = "退款申请人")
    private String applicant;

    @Schema(description = "操作退款用户userId")
    private String refundUserId;

    @Schema(description = "退款金额")
    private BigDecimal refundAMount;

    @Schema(description = "退款状态")
    private RefundState refundState;

    @Schema(description = "申请退款时间")
    private Long refundTime;

    @Schema(description = "申请退款备注")
    private String refundRemark;

    @Schema(description = "退款处理备注")
    private String refuseRemark;

    @Schema(description = "退款订单号")
    private String refundNo;

    @Schema(description = "退款账单流量")
    private List<TransactionLogModel> refundTransactionIds = new ArrayList<TransactionLogModel>();

    @Schema(description = "最新关联的退款数据")
    @DBRef(lazy = true)
    private RefundRecord refundRecord;

    //-------------------------结算信息 start ----------------

    @Schema(description = "结算状态")
    private SettlementState settlementState = SettlementState.Unsettled;

    @Schema(description = "结算时间")
    private Long settlementTime;

    /**
     * 设置支付失败
     *
     * @param msg
     */
    public void setPayFailed(String msg) {
        this.paymentStatus = "支付失败";
        this.isPaySuccess = Boolean.FALSE;
        this.payRemark = msg;
        this.orderState = OrderState.PAID_ERROR;
        this.isPaid = Boolean.TRUE;
    }
}
