package com.ruoyi.ss.receiveBill.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.receiveBill.domain.ReceiveBill;
import com.ruoyi.ss.receiveBill.domain.ReceiveBillQuery;
import com.ruoyi.ss.receiveBill.domain.ReceiveBillVO;
import com.ruoyi.ss.receiveBill.domain.enums.ReceiveBillStatus;
import com.ruoyi.ss.receiveBill.domain.enums.ReceiveBillType;
import com.ruoyi.ss.receiveBill.domain.vo.ReceiveAmountVO;
import com.ruoyi.ss.receiveBill.mapper.ReceiveBillMapper;
import com.ruoyi.ss.receiveBill.service.ReceiveBillService;
import com.ruoyi.ss.recordBalance.domain.enums.RecordBalanceBstType;
import com.ruoyi.ss.transactionBill.service.impl.TransactionBillServiceImpl;
import com.ruoyi.ss.user.domain.SmUserVO;
import com.ruoyi.ss.user.service.ISmUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 应收账单Service业务层处理
 *
 * @author ruoyi
 * @date 2024-07-22
 */
@Service
public class ReceiveBillServiceImpl implements ReceiveBillService
{
    @Autowired
    private ReceiveBillMapper receiveBillMapper;

    @Autowired
    private ISmUserService userService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private TransactionBillServiceImpl transactionBillService;

    /**
     * 查询应收账单
     *
     * @param billId 应收账单主键
     * @return 应收账单
     */
    @Override
    public ReceiveBillVO selectReceiveBillByBillId(Long billId)
    {
        return receiveBillMapper.selectReceiveBillByBillId(billId);
    }

    /**
     * 查询应收账单列表
     *
     * @param receiveBill 应收账单
     * @return 应收账单
     */
    @Override
    public List<ReceiveBillVO> selectReceiveBillList(ReceiveBillQuery receiveBill)
    {
        return receiveBillMapper.selectReceiveBillList(receiveBill);
    }

    /**
     * 新增应收账单
     *
     * @param receiveBill 应收账单
     * @return 结果
     */
    @Override
    public int insertReceiveBill(ReceiveBill receiveBill)
    {
        receiveBill.setCreateTime(DateUtils.getNowDate());
        return receiveBillMapper.insertReceiveBill(receiveBill);
    }

    /**
     * 修改应收账单
     *
     * @param receiveBill 应收账单
     * @return 结果
     */
    @Override
    public int updateReceiveBill(ReceiveBill receiveBill)
    {
        return receiveBillMapper.updateReceiveBill(receiveBill);
    }

    /**
     * 批量删除应收账单
     *
     * @param billIds 需要删除的应收账单主键
     * @return 结果
     */
    @Override
    public int deleteReceiveBillByBillIds(Long[] billIds)
    {
        return receiveBillMapper.deleteReceiveBillByBillIds(billIds);
    }

    /**
     * 删除应收账单信息
     *
     * @param billId 应收账单主键
     * @return 结果
     */
    @Override
    public int deleteReceiveBillByBillId(Long billId)
    {
        return receiveBillMapper.deleteReceiveBillByBillId(billId);
    }

    @Override
    public int genBillByMonthAndPay(SmUserVO mch, DeviceVO device) {
        ServiceUtil.assertion(mch == null || mch.getUserId() == null, "商户不存在");
        ServiceUtil.assertion(device == null || device.getDeviceId() == null, "设备不存在");

        LocalDateTime billTime = LocalDateTime.now();
        // 设备未过期，则不生成账单
        if (device.getRentTime() != null && device.getRentTime().isAfter(billTime)) {
            return 1;
        }
        // 设备月费若为空或者0，则不收取
        if (device.getMonthFee() == null || device.getMonthFee().compareTo(BigDecimal.ZERO) == 0) {
            return 1;
        }

        BigDecimal amount = device.getMonthFee();

        // 生成账单
        ReceiveBill bill = new ReceiveBill();
        bill.setUserId(mch.getUserId());
        bill.setDeviceId(device.getDeviceId());
        bill.setType(ReceiveBillType.MONTH.getType());
        bill.setStatus(ReceiveBillStatus.PAID.getStatus());
        bill.setBillTime(billTime);
        bill.setAmount(amount);
        bill.setDescription(String.format("%s年%s月-设备%s月费", billTime.getYear(), billTime.getMonthValue(), device.getDeviceNo()));
        bill.setReceivedAmount(amount);
        Integer result = transactionTemplate.execute(status -> {
            // 插入账单
            int insert = this.insertReceiveBill(bill);
            ServiceUtil.assertion(insert != 1, "新增账单失败");

            // 用户余额扣减
            int subtract = userService.subtractBalance(mch.getUserId(), amount, false, bill.getDescription(), RecordBalanceBstType.RECEIVABLE, bill.getBillId());
            ServiceUtil.assertion(subtract != 1, "扣减商户余额失败");

            // 设备续费30天
            int renewal = deviceService.renewalRentTime(device.getDeviceId(), 30, TimeUnit.DAYS);
            ServiceUtil.assertion(renewal != 1, "设备续费失败");

            return insert;
        });

        return result == null ? 0 : result;
    }

    @Override
    public int selectCount(ReceiveBillQuery query) {
        return receiveBillMapper.selectCount(query);
    }

    @Override
    public BigDecimal selectSumOfAmount(ReceiveBillQuery query) {
        return receiveBillMapper.selectSumOfAmount(query);
    }

    @Override
    public <K> List<ReceiveAmountVO<K>> selectCommonSumOfAmount(ReceiveBillQuery query, String groupBy) {
        return receiveBillMapper.selectCommonSumOfAmount(query, groupBy);
    }

}
