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

import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.ss.account.domain.AccountQuery;
import com.ruoyi.ss.account.domain.AccountVO;
import com.ruoyi.ss.account.service.AccountService;
import com.ruoyi.ss.channel.service.ChannelService;
import com.ruoyi.ss.channelWithdraw.domain.ChannelWithdrawVO;
import com.ruoyi.ss.channelWithdraw.service.ChannelWithdrawService;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.device.service.DeviceAssembler;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.store.domain.StoreVo;
import com.ruoyi.ss.store.service.StoreService;
import com.ruoyi.ss.suit.domain.SuitVO;
import com.ruoyi.ss.suit.domain.enums.SuitFeeMode;
import com.ruoyi.ss.suit.domain.enums.SuitTimeUnit;
import com.ruoyi.ss.suit.service.SuitAssembler;
import com.ruoyi.ss.suit.service.SuitService;
import com.ruoyi.ss.transactionBill.domain.bo.*;
import com.ruoyi.ss.transactionBill.domain.dto.*;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
import com.ruoyi.ss.transactionBill.service.TransactionBillConverter;
import com.ruoyi.ss.user.domain.SmUserVO;
import com.ruoyi.ss.user.service.ISmUserService;
import com.ruoyi.system.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;

/**
 * @author wjh
 * 2024/7/28
 */
@Service
public class TransactionBillConverterImpl implements TransactionBillConverter {

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private ISmUserService userService;

    @Autowired
    private SuitService suitService;

    @Autowired
    private ChannelService channelService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private SuitAssembler suitAssembler;

    @Autowired
    private StoreService storeService;

    @Autowired
    private ChannelWithdrawService channelWithdrawService;

    @Autowired
    private TransactionBillServiceImpl transactionBillService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private DeviceAssembler deviceAssembler;

    /**
     * 将参数转为充值BO
     *
     * @param dto
     */
    @Override
    public RechargeBO toRechargeBO(RechargeDTO dto) {
        if (dto == null) {
            return null;
        }

        DeviceVO device = deviceService.selectByDeviceNo(dto.getDeviceNo());
        ServiceUtil.assertion(device == null, "设备不存在");
        deviceAssembler.assembleBonusList(Collections.singletonList(device));   // 拼接分成列表

        StoreVo store = storeService.selectSmStoreById(device.getStoreId());

        SmUserVO mch = userService.selectSmUserByUserId(device.getUserId());
        ServiceUtil.assertion(mch == null, "商户不存在");

        SuitVO suit = suitService.selectSuitBySuitId(dto.getSuitId());
        ServiceUtil.assertion(suit == null, "套餐不存在");
        suitAssembler.assembleDeviceList(Collections.singletonList(suit));

        SmUserVO user = userService.selectSmUserByUserId(SecurityUtils.getUserId());
        ServiceUtil.assertion(user == null, "用户不存在");

        RechargeBO bo = new RechargeBO();
        bo.setDevice(device);
        bo.setUser(user);
        bo.setSuit(suit);
        bo.setMch(mch);
        bo.setParams(dto);
        bo.setStore(store);
        bo.setPlatform(deptService.selectDeptById(Constants.ROOT_DEPT));
        bo.setAgent(userService.selectSmUserByUserId(device.getAgentId()));
        return bo;
    }

    /**
     * 将参数转为提现BO
     *
     * @param dto
     */
    @Override
    public WithdrawBO toWithdrawBO(WithdrawDTO dto) {
        if (dto == null) {
            return null;
        }

        // 用户
        SmUserVO user = userService.selectSmUserByUserId(dto.getUserId());
        ServiceUtil.assertion(user == null, "用户不存在");

        // 渠道
        ChannelWithdrawVO channel = channelWithdrawService.selectChannelWithdrawByChannelId(dto.getChannelId());
        ServiceUtil.assertion(channel == null, "提现渠道不存在");
        ServiceUtil.assertion(channel.getEnabled() == null || !channel.getEnabled(), "提现渠道不可用");

        // 获取收款账户
        ServiceUtil.assertion(StringUtils.isBlank(channel.getAccountType()), "提现渠道没有对应的收款账户类型，请联系管理员处理");
        AccountQuery accountQuery = new AccountQuery();
        accountQuery.setUserId(user.getUserId());
        accountQuery.setAccountType(channel.getAccountType());
        AccountVO account = accountService.selectOne(accountQuery);
        ServiceUtil.assertion(account == null, "收款账户不存在");

        WithdrawBO bo = new WithdrawBO();
        bo.setDto(dto);
        bo.setUser(user);
        bo.setChannel(channel);
        bo.setAccount(account);
        return bo;
    }

    @Override
    public RechargePayBO toRechargePayBO(TransactionBillVO bill, Long channelId) {
        if (bill == null) {
            return null;
        }

        RechargePayBO bo = new RechargePayBO();
        bo.setOrder(bill);
        bo.setUser(userService.selectSmUserByUserId(bill.getUserId()));
        bo.setMch(userService.selectSmUserByUserId(bill.getMchId()));
        bo.setDevice(deviceService.selectById(bill.getDeviceId()));
        bo.setChannel(channelService.selectSmChannelByChannelId(channelId));
        bo.setPlatform(deptService.selectDeptById(Constants.ROOT_DEPT));
        return bo;
    }

    @Override
    public RechargePayDepositBO toRechargePayDepositBO(PayDepositDTO dto) {
        if (dto == null) {
            return null;
        }
        TransactionBillVO order = transactionBillService.selectSmTransactionBillByBillNo(dto.getBillNo());

        RechargePayDepositBO bo = new RechargePayDepositBO();
        bo.setDto(dto);
        bo.setChannel(channelService.selectSmChannelByChannelId(dto.getChannelId()));
        bo.setOrder(order);
        if (order != null) {
            bo.setUser(userService.selectSmUserByUserId(order.getUserId()));
        }
        return bo;
    }

    @Override
    public EndUseBO toEndUseBO(EndUseDTO dto) {

        if (dto == null) {
            return null;
        }
        TransactionBillVO order = transactionBillService.selectSmTransactionBillByBillId(dto.getBillId());

        EndUseBO bo = new EndUseBO();
        bo.setOrder(order);
        bo.setTotalEle(dto.getTotalEle());
        if (order != null) {
            DeviceVO device = deviceService.selectById(order.getDeviceId());
            deviceService.pullDeviceInfo(device);
            bo.setDevice(device);
        }
        return bo;
    }

    @Override
    public BigDecimal toRechargeEle(TransactionBillVO bill) {
        if (bill == null) {
            return BigDecimal.ZERO;
        }
        // 计算周期数
        long round = this.calcRound(bill);
        return BigDecimal.valueOf(bill.getSuitTime() * round);
    }

    @Override
    public long toRechargeSeconds(TransactionBillVO bill) {
        long round = this.calcRound(bill);
        return this.toSecondSuitTime(bill) * round;
    }

    @Override
    public long toSecondSuitTime(TransactionBillVO bill) {
        SuitTimeUnit unit = SuitTimeUnit.getByValue(bill.getSuitTimeUnit());
        if (unit == null) {
            unit = SuitTimeUnit.MINUTE;
        }
        long time = bill.getSuitTime() == null ? 0 : bill.getSuitTime();
        return time * unit.getConversion();
    }

    /**
     * 计算周期数
     */
    private long calcRound(TransactionBillVO bill) {
        int round = 1;
        // 若为智能模式，则计算出押金最大支持多少次，向上取整
        if (SuitFeeMode.SMART.getMode().equals(bill.getSuitFeeMode())) {
            round = bill.getSuitDeposit().divide(bill.getSuitPrice(), 0, RoundingMode.UP).intValue();
        }
        return round;
    }
}
