package com.czg.order.entity;

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * 店铺订单统计报表 实体类。
 *
 * @author ww
 * @since 2025-11-20
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table("tb_shop_order_statistic")
public class ShopOrderStatistic implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 检查订单统计数据是否有效
     *
     * @param stat 订单统计数据
     * @return 是否有效
     */
    public boolean hasValidData(ShopOrderStatistic stat) {
        if (stat == null) {
            return false;
        }
        // 检查BigDecimal类型字段             检查Long类型字段
        return checkBigDecimalFields(stat) && checkLongFields(stat);
    }

    /**
     *
     * 初始化空白数据 标识为 无效数据 valid = false
     */
    public void init() {
        this.valid = false;
        this.originAmount = zero;
        this.payAmount = zero;
        this.refundAmount = zero;
        this.onlineRefundAmount = zero;
        this.cashRefundAmount = zero;
        this.memberRefundAmount = zero;
        this.memberPayAmount = zero;
        this.memberPayCount = 0L;
        this.rechargeAmount = zero;
        this.onlineRechargeAmount = zero;
        this.cashRechargeAmount = zero;
        this.giveAmount = zero;
        this.rechargeRefundAmount = zero;
        this.onlineRechargeRefundAmount = zero;
        this.cashRechargeRefundAmount = zero;
        this.newMemberCount = 0L;
        this.customerCount = 0L;
        this.orderCount = 0L;
        this.tableCount = 0L;
        this.avgPayAmount = zero;
        this.turnoverRate = zero;
        this.profitAmount = zero;
        this.productCostAmount = zero;
        this.profitRate = zero;
        this.netProfitAmount = zero;
        this.netProfitRate = zero;
        this.discountAmount = zero;
        this.discountCount = 0L;
        this.newCustomerDiscountAmount = zero;
        this.fullDiscountAmount = zero;
        this.couponDiscountAmount = zero;
        this.pointDiscountAmount = zero;
        this.backDiscountAmount = zero;
        this.memberDiscountAmount = zero;
        this.orderPriceDiscountAmount = zero;
        this.onlinePayAmount = zero;
        this.cashPayAmount = zero;
        this.wechatPayAmount = zero;
        this.alipayPayAmount = zero;
        this.backScanPayAmount = zero;
        this.mainScanPayAmount = zero;
        this.creditPayAmount = zero;
        this.cashPayCount = 0L;
        this.wechatPayCount = 0L;
        this.alipayPayCount = 0L;
        this.backScanPayCount = 0L;
        this.mainScanPayCount = 0L;
        this.creditPayCount = 0L;


    }


    /**
     * 主键ID
     */
    @Id(keyType = KeyType.Auto)
    @ExcelIgnore
    private Integer id;

    /**
     * 店铺id
     */
    @ExcelIgnore
    private Long shopId;
    /**
     * 统计日期 yyyy-MM-dd
     */
    @ExcelProperty("统计日期")
    @ColumnWidth(17)
    private LocalDate statisticDate;

    /**
     * 订单金额 订单原金额
     */
    @ExcelProperty("订单金额")
    private BigDecimal originAmount;

    /**
     * 实付金额 (线上付款 现金支付 会员支付 挂账)
     */
    @ExcelProperty("实付金额")
    private BigDecimal payAmount;


    //*********************以下为支付金额********************************************************************************
    /**
     * 现金支付金额
     */
    @ExcelProperty("现金支付金额")
    private BigDecimal cashPayAmount;
    @ExcelIgnore
    private BigDecimal cashPayAmountOriginal;
    /**
     * 现金支付笔数
     */
    @ExcelProperty("现金支付笔数")
    private Long cashPayCount;
    /**
     * 微信小程序支付金额
     */
    @ExcelProperty("微信小程序支付金额")
    private BigDecimal wechatPayAmount;
    @ExcelIgnore
    private BigDecimal wechatPayAmountOriginal;
    /**
     * 微信小程序支付笔数
     */
    @ExcelProperty("微信小程序支付笔数")
    private Long wechatPayCount;
    /**
     * 支付宝小程序支付金额
     */
    @ExcelProperty("支付宝小程序支付金额")
    private BigDecimal alipayPayAmount;
    @ExcelIgnore
    private BigDecimal alipayPayAmountOriginal;
    /**
     * 支付宝小程序支付笔数
     */
    @ExcelProperty("支付宝小程序支付笔数")
    private Long alipayPayCount;
    /**
     * 被扫收款金额
     */
    @ExcelProperty("扫码收款金额")
    private BigDecimal backScanPayAmount;
    @ExcelIgnore
    private BigDecimal backScanPayAmountOriginal;
    /**
     * 被扫收款笔数
     */
    @ExcelProperty("扫码收款笔数")
    private Long backScanPayCount;
    /**
     * 二维码收款金额
     */
    @ExcelProperty("二维码收款金额")
    private BigDecimal mainScanPayAmount;
    @ExcelIgnore
    private BigDecimal mainScanPayAmountOriginal;
    /**
     * 二维码收款笔数
     */
    @ExcelProperty("二维码收款笔数")
    private Long mainScanPayCount;
    /**
     * 挂账支付金额
     */
    @ExcelProperty("挂账支付金额")
    private BigDecimal creditPayAmount;
    @ExcelIgnore
    private BigDecimal creditPayAmountOriginal;
    /**
     * 挂账支付笔数
     */
    @ExcelProperty("挂账支付笔数")
    private Long creditPayCount;

    /**
     * 会员消费 会员订单支付金额
     */
    @ExcelProperty("会员消费金额")
    private BigDecimal memberPayAmount;
    @ExcelIgnore
    private BigDecimal memberPayAmountOriginal;
    /**
     * 会员消费笔数
     */
    @ExcelProperty("会员消费笔数")
    private Long memberPayCount;

    //*********************以下为订单金额********************************************************************************


    /**
     * 线上付款金额
     */
    @ExcelProperty("线上付款金额")
    private BigDecimal onlinePayAmount;
    /**
     * 订单退款 退款金额(原路返回 现金退款)
     */
    @ExcelProperty("订单退款金额")
    private BigDecimal refundAmount;

    @ExcelIgnore
    private Long refundCount;
    @ExcelProperty("订单挂账退款金额")
    private BigDecimal creditRefundAmount;
    /**
     * 订单退款 线上退款金额
     */
    @ExcelProperty("订单退款线上金额")
    private BigDecimal onlineRefundAmount;
    /**
     * 订单退款 线下退款金额/现金退款金额
     */
    @ExcelProperty("订单退款线下金额")
    private BigDecimal cashRefundAmount;
    /**
     * 订单退款 会员退款金额
     */
    @ExcelProperty("订单退款会员金额")
    private BigDecimal memberRefundAmount;


    //*********************以下为充值金额********************************************************************************
    /**
     * 会员充值 充值金额(包含现金支付) 不包括赠送   多店 按 主店算
     */
    @ExcelProperty("会员充值金额")
    private BigDecimal rechargeAmount;
    /**
     * 会员充值 线上充值金额
     */
    @ExcelProperty("会员线上充值金额")
    private BigDecimal onlineRechargeAmount;
    /**
     * 会员充值 现金充值金额
     */
    @ExcelProperty("会员现金充值金额")
    private BigDecimal cashRechargeAmount;
    /**
     * 会员充值 充值赠送金额
     */
    @ExcelProperty("会员充值赠送金额")
    private BigDecimal giveAmount;

    /**
     * 会员充值退款 充值退款金额（线上退款+现金退款）
     */
    @ExcelProperty("会员充值退款金额")
    private BigDecimal rechargeRefundAmount;
    /**
     * 会员充值退款 线上退款
     */
    @ExcelProperty("会员充值线上退款金额")
    private BigDecimal onlineRechargeRefundAmount;
    /**
     * 会员充值退款 现金退款金额
     */
    @ExcelProperty("会员充值线下退款金额")
    private BigDecimal cashRechargeRefundAmount;
    /**
     * 新增会员数
     */
    @ExcelProperty("新增会员数")
    private Long newMemberCount;


    //*********************以下为优惠金额********************************************************************************
    /**
     * 优惠总金额
     */
    @ExcelProperty("优惠总金额")
    private BigDecimal discountAmount;
    /**
     * 优惠笔数
     */
    @ExcelProperty("优惠笔数")
    private Long discountCount;

    /**
     * 新客立减金额
     */
    @ExcelProperty("新客立减金额")
    private BigDecimal newCustomerDiscountAmount;
    /**
     * 满减活动金额
     */
    @ExcelProperty("满减活动金额")
    private BigDecimal fullDiscountAmount;
    /**
     * 优惠券抵扣金额
     */
    @ExcelProperty("优惠券抵扣金额")
    private BigDecimal couponDiscountAmount;
    /**
     * 积分抵扣金额
     */
    @ExcelProperty("积分抵扣金额")
    private BigDecimal pointDiscountAmount;
    /**
     * 霸王餐金额
     */
    @ExcelProperty("霸王餐金额")
    private BigDecimal backDiscountAmount;
    /**
     * 会员整单折扣金额
     */
    @ExcelProperty("会员整单折扣金额")
    private BigDecimal memberDiscountAmount;
    /**
     * 订单改价金额
     */
    @ExcelProperty("订单改价金额")
    private BigDecimal orderPriceDiscountAmount;


    //*********************以下为客单价 翻台率 的计算********************************************************************************
    /**
     * 就餐人数
     */
    @ExcelProperty("就餐人数")
    private Long customerCount;
    /**
     * 订单数
     */
    @ExcelProperty("订单数")
    private Long orderCount;
    /**
     * 桌台数
     */
    @ExcelProperty("桌台数")
    private Long tableCount;
    /**
     * 客单价
     * 实付金额(包含现金支付 包含会员支付 包含挂账)/就餐人数
     * 没有具体人数时，默认一桌按照1人计算
     */
    @ExcelProperty("客单价")
    private BigDecimal avgPayAmount;
    /**
     * 翻台率
     * （订单数-桌台数）/桌台数*100%
     */
    @ExcelProperty("翻台率(%)")
    private BigDecimal turnoverRate;

    /**
     * 毛利润（订单实付金额-商品成本）
     */
    @ExcelProperty("毛利率(%)")
    private BigDecimal profitAmount;
    /**
     * 商品成本
     */
    @ExcelProperty("商品成本")
    private BigDecimal productCostAmount;
    /**
     * 毛利率（订单实付金额-商品成本）/订单实付金额*100%
     */
    @ExcelProperty("利润率(%)")
    private BigDecimal profitRate;
    /**
     * 净利润
     */
    @ExcelProperty("净利润")
    private BigDecimal netProfitAmount;
    /**
     * 净利润率
     */
    @ExcelProperty("净利润率(%)")
    private BigDecimal netProfitRate;

    /**
     * 抖音团购
     */
    @ExcelIgnore
    private BigDecimal douyinGroup;

    /**
     * 美团团购
     */
    @ExcelIgnore
    private BigDecimal meituanGroup;

    /**
     * 整单退款数量
     */
    @ExcelIgnore
    private Long refundAllNum;

    /**
     * 整单退款金额
     */
    @ExcelIgnore
    private BigDecimal refundAllAmount;

    /**
     * 单菜品退款数量
     */
    @ExcelIgnore
    private Long refundItemNum;
    /**
     * 单菜品退款金额
     */
    @ExcelIgnore
    private BigDecimal refundItemAmount;

    /**
     * 折扣订单数量
     */
    @ExcelIgnore
    private Long discountOrderNum;
    /**
     * 折扣订单金额
     */
    @ExcelIgnore
    private BigDecimal discountOrderAmount;

    /**
     * 待支付订单数量
     */
    @ExcelIgnore
    private Long unpaidOrderNum;
    /**
     * 待支付订单金额
     */
    @ExcelIgnore
    private BigDecimal unpaidOrderAmount;

    /**
     * 创建时间
     */
    @ExcelIgnore
    @Column(onInsertValue = "now()")
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    @ExcelIgnore
    @Column(onInsertValue = "now()", onUpdateValue = "now()")
    private LocalDateTime updateTime;

    @Column(ignore = true)
    @ExcelIgnore
    BigDecimal zero = BigDecimal.ZERO;

    /**
     * 是否有效
     */
    @Column(ignore = true)
    @ExcelIgnore
    private Boolean valid = true;


    private static boolean checkBigDecimalFields(ShopOrderStatistic stat) {
        return
                isGreaterThanZero(stat.getOriginAmount()) ||
                isGreaterThanZero(stat.getPayAmount()) ||
                isGreaterThanZero(stat.getRefundAmount()) ||
                isGreaterThanZero(stat.getOnlineRefundAmount()) ||
                isGreaterThanZero(stat.getCashRefundAmount()) ||
                isGreaterThanZero(stat.getMemberRefundAmount()) ||
                isGreaterThanZero(stat.getMemberPayAmount()) ||
                isGreaterThanZero(stat.getRechargeAmount()) ||
                isGreaterThanZero(stat.getOnlineRechargeAmount()) ||
                isGreaterThanZero(stat.getCashRechargeAmount()) ||
                isGreaterThanZero(stat.getGiveAmount()) ||
                isGreaterThanZero(stat.getRechargeRefundAmount()) ||
                isGreaterThanZero(stat.getOnlineRechargeRefundAmount()) ||
                isGreaterThanZero(stat.getCashRechargeRefundAmount()) ||
                isGreaterThanZero(stat.getAvgPayAmount()) ||
                isGreaterThanZero(stat.getTurnoverRate()) ||
                isGreaterThanZero(stat.getProfitAmount()) ||
                isGreaterThanZero(stat.getProductCostAmount()) ||
                isGreaterThanZero(stat.getProfitRate()) ||
                isGreaterThanZero(stat.getNetProfitAmount()) ||
                isGreaterThanZero(stat.getNetProfitRate()) ||
                isGreaterThanZero(stat.getDiscountAmount()) ||
                isGreaterThanZero(stat.getNewCustomerDiscountAmount()) ||
                isGreaterThanZero(stat.getFullDiscountAmount()) ||
                isGreaterThanZero(stat.getCouponDiscountAmount()) ||
                isGreaterThanZero(stat.getPointDiscountAmount()) ||
                isGreaterThanZero(stat.getBackDiscountAmount()) ||
                isGreaterThanZero(stat.getMemberDiscountAmount()) ||
                isGreaterThanZero(stat.getOrderPriceDiscountAmount()) ||
                isGreaterThanZero(stat.getOnlinePayAmount()) ||
                isGreaterThanZero(stat.getCashPayAmount()) ||
                isGreaterThanZero(stat.getWechatPayAmount()) ||
                isGreaterThanZero(stat.getAlipayPayAmount()) ||
                isGreaterThanZero(stat.getBackScanPayAmount()) ||
                isGreaterThanZero(stat.getMainScanPayAmount()) ||
                isGreaterThanZero(stat.getCreditPayAmount());
    }

    private static boolean checkLongFields(ShopOrderStatistic stat) {
        return (stat.getMemberPayCount() != null && stat.getMemberPayCount() > 0) ||
                (stat.getNewMemberCount() != null && stat.getNewMemberCount() > 0) ||
                (stat.getCustomerCount() != null && stat.getCustomerCount() > 0) ||
                (stat.getOrderCount() != null && stat.getOrderCount() > 0) ||
                (stat.getTableCount() != null && stat.getTableCount() > 0) ||
                (stat.getDiscountCount() != null && stat.getDiscountCount() > 0) ||
                (stat.getCashPayCount() != null && stat.getCashPayCount() > 0) ||
                (stat.getWechatPayCount() != null && stat.getWechatPayCount() > 0) ||
                (stat.getAlipayPayCount() != null && stat.getAlipayPayCount() > 0) ||
                (stat.getBackScanPayCount() != null && stat.getBackScanPayCount() > 0) ||
                (stat.getMainScanPayCount() != null && stat.getMainScanPayCount() > 0) ||
                (stat.getCreditPayCount() != null && stat.getCreditPayCount() > 0);
    }

    /**
     * 合并两个统计对象
     */
    public static ShopOrderStatistic mergeStatistics(ShopOrderStatistic stat1, ShopOrderStatistic stat2) {
        if (stat2 == null) {
            return stat1;
        }
        if (stat1 == null) {
            return stat2;
        }

        if(!stat2.getValid()) {
            return stat1;
        }
        if(!stat1.getValid()) {
            return stat2;
        }

        ShopOrderStatistic result = new ShopOrderStatistic();

        // 合并BigDecimal字段
        result.setOriginAmount(safeAdd(stat1.getOriginAmount(), stat2.getOriginAmount()));
        result.setPayAmount(safeAdd(stat1.getPayAmount(), stat2.getPayAmount()));
        result.setRefundAmount(safeAdd(stat1.getRefundAmount(), stat2.getRefundAmount()));
        result.setOnlineRefundAmount(safeAdd(stat1.getOnlineRefundAmount(), stat2.getOnlineRefundAmount()));
        result.setCashRefundAmount(safeAdd(stat1.getCashRefundAmount(), stat2.getCashRefundAmount()));
        result.setMemberRefundAmount(safeAdd(stat1.getMemberRefundAmount(), stat2.getMemberRefundAmount()));
        result.setMemberPayAmount(safeAdd(stat1.getMemberPayAmount(), stat2.getMemberPayAmount()));
        result.setRechargeAmount(safeAdd(stat1.getRechargeAmount(), stat2.getRechargeAmount()));
        result.setOnlineRechargeAmount(safeAdd(stat1.getOnlineRechargeAmount(), stat2.getOnlineRechargeAmount()));
        result.setCashRechargeAmount(safeAdd(stat1.getCashRechargeAmount(), stat2.getCashRechargeAmount()));
        result.setGiveAmount(safeAdd(stat1.getGiveAmount(), stat2.getGiveAmount()));
        result.setRechargeRefundAmount(safeAdd(stat1.getRechargeRefundAmount(), stat2.getRechargeRefundAmount()));
        result.setOnlineRechargeRefundAmount(safeAdd(stat1.getOnlineRechargeRefundAmount(), stat2.getOnlineRechargeRefundAmount()));
        result.setCashRechargeRefundAmount(safeAdd(stat1.getCashRechargeRefundAmount(), stat2.getCashRechargeRefundAmount()));
//        result.setAvgPayAmount(safeAdd(stat1.getAvgPayAmount(), stat2.getAvgPayAmount()));
//        result.setTurnoverRate(safeAdd(stat1.getTurnoverRate(), stat2.getTurnoverRate()));
//        result.setProfitAmount(safeAdd(stat1.getProfitAmount(), stat2.getProfitAmount()));
        result.setProductCostAmount(safeAdd(stat1.getProductCostAmount(), stat2.getProductCostAmount()));
//        result.setProfitRate(safeAdd(stat1.getProfitRate(), stat2.getProfitRate()));
        result.setNetProfitAmount(safeAdd(stat1.getNetProfitAmount(), stat2.getNetProfitAmount()));
//        result.setNetProfitRate(safeAdd(stat1.getNetProfitRate(), stat2.getNetProfitRate()));
        result.setDiscountAmount(safeAdd(stat1.getDiscountAmount(), stat2.getDiscountAmount()));
        result.setNewCustomerDiscountAmount(safeAdd(stat1.getNewCustomerDiscountAmount(), stat2.getNewCustomerDiscountAmount()));
        result.setFullDiscountAmount(safeAdd(stat1.getFullDiscountAmount(), stat2.getFullDiscountAmount()));
        result.setCouponDiscountAmount(safeAdd(stat1.getCouponDiscountAmount(), stat2.getCouponDiscountAmount()));
        result.setPointDiscountAmount(safeAdd(stat1.getPointDiscountAmount(), stat2.getPointDiscountAmount()));
        result.setBackDiscountAmount(safeAdd(stat1.getBackDiscountAmount(), stat2.getBackDiscountAmount()));
        result.setMemberDiscountAmount(safeAdd(stat1.getMemberDiscountAmount(), stat2.getMemberDiscountAmount()));
        result.setOrderPriceDiscountAmount(safeAdd(stat1.getOrderPriceDiscountAmount(), stat2.getOrderPriceDiscountAmount()));
        result.setOnlinePayAmount(safeAdd(stat1.getOnlinePayAmount(), stat2.getOnlinePayAmount()));
        result.setCashPayAmount(safeAdd(stat1.getCashPayAmount(), stat2.getCashPayAmount()));
        result.setWechatPayAmount(safeAdd(stat1.getWechatPayAmount(), stat2.getWechatPayAmount()));
        result.setAlipayPayAmount(safeAdd(stat1.getAlipayPayAmount(), stat2.getAlipayPayAmount()));
        result.setBackScanPayAmount(safeAdd(stat1.getBackScanPayAmount(), stat2.getBackScanPayAmount()));
        result.setMainScanPayAmount(safeAdd(stat1.getMainScanPayAmount(), stat2.getMainScanPayAmount()));
        result.setCreditPayAmount(safeAdd(stat1.getCreditPayAmount(), stat2.getCreditPayAmount()));

        // 合并Long字段
        result.setMemberPayCount(safeAdd(stat1.getMemberPayCount(), stat2.getMemberPayCount()));
        result.setNewMemberCount(safeAdd(stat1.getNewMemberCount(), stat2.getNewMemberCount()));
        result.setCustomerCount(safeAdd(stat1.getCustomerCount(), stat2.getCustomerCount()));
        result.setOrderCount(safeAdd(stat1.getOrderCount(), stat2.getOrderCount()));
        result.setTableCount(stat1.getTableCount());
        result.setDiscountCount(safeAdd(stat1.getDiscountCount(), stat2.getDiscountCount()));
        result.setCashPayCount(safeAdd(stat1.getCashPayCount(), stat2.getCashPayCount()));
        result.setWechatPayCount(safeAdd(stat1.getWechatPayCount(), stat2.getWechatPayCount()));
        result.setAlipayPayCount(safeAdd(stat1.getAlipayPayCount(), stat2.getAlipayPayCount()));
        result.setBackScanPayCount(safeAdd(stat1.getBackScanPayCount(), stat2.getBackScanPayCount()));
        result.setMainScanPayCount(safeAdd(stat1.getMainScanPayCount(), stat2.getMainScanPayCount()));
        result.setCreditPayCount(safeAdd(stat1.getCreditPayCount(), stat2.getCreditPayCount()));

        return result;
    }

    /**
     * 安全的BigDecimal相加
     */
    private static BigDecimal safeAdd(BigDecimal num1, BigDecimal num2) {
        if (num1 == null) {
            return num2;
        }
        if (num2 == null) {
            return num1;
        }
        return num1.add(num2);
    }

    /**
     * 安全的Long相加
     */
    private static Long safeAdd(Long num1, Long num2) {
        if (num1 == null) {
            return num2;
        }
        if (num2 == null) {
            return num1;
        }
        return num1 + num2;
    }

    private static boolean isGreaterThanZero(BigDecimal value) {
        return value != null && value.compareTo(BigDecimal.ZERO) > 0;
    }

}
