package com.ycwl.basic.profitsharing.biz;

import com.ycwl.basic.profitsharing.entity.ProfitSharingConfig;
import com.ycwl.basic.profitsharing.entity.ProfitSharingRecord;
import com.ycwl.basic.profitsharing.entity.ProfitSharingUser;
import com.ycwl.basic.profitsharing.mapper.ProfitSharingRecordMapper;
import com.ycwl.basic.profitsharing.repository.ProfitSharingRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ProfitSharingBiz {
    @Autowired
    private ProfitSharingRepository repository;

    @Autowired
    private ProfitSharingRecordMapper recordMapper;

    public void processProfitSharing(Long scenicId, Long orderId, BigDecimal amount) {
        log.info("开始处理分账，当前景区{},订单{},金额{}", scenicId, orderId, amount);
        ProfitSharingConfig config = repository.getScenicConfig(scenicId);
        if (config == null || config.getUsers() == null || config.getUsers().isEmpty()) {
            return;
        }
        List<ProfitSharingRecord> records = new ArrayList<>();
        List<ProfitSharingUser> alreadyProcessedUsers = new ArrayList<>();
        // 先找出1,3的用户
        config.getUsers().stream().filter(user -> user.getRateMode() == 1 || user.getRateMode() == 3).forEach(user -> {
            if (alreadyProcessedUsers.contains(user)) {
                return;
            }
            BigDecimal userAmount;
            BigDecimal wxAmount;
            BigDecimal manualAmount;
            if (user.getRateMode() == 1) { // 比例抽成
                userAmount = amount.multiply(user.getRealRate()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN);
                wxAmount = amount.multiply(user.getWxRate()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN);
                manualAmount = userAmount.subtract(wxAmount);
            } else { // 固定抽成
                userAmount = user.getRealRate();
                wxAmount = user.getWxRate();
                manualAmount = userAmount.subtract(wxAmount);
            }
            ProfitSharingRecord record = new ProfitSharingRecord();
            record.setScenicId(scenicId);
            record.setOrderId(orderId);
            record.setUserId(user.getId());
            record.setUserName(user.getName());
            record.setAmount(userAmount);
            record.setWxAmount(wxAmount);
            record.setManualAmount(manualAmount);
            record.setRateMode(user.getRateMode());
            record.setWxRate(user.getWxRate());
            record.setRealRate(user.getRealRate());
            record.setOrderAmount(amount);
            record.setCreateTime(new Date());
            records.add(record);
            alreadyProcessedUsers.add(user);
        });
        final BigDecimal mode2RemainAmount = amount.subtract(records.stream().map(ProfitSharingRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 找出2的用户
        config.getUsers().stream().filter(user -> user.getRateMode() == 2).forEach(user -> {
            if (alreadyProcessedUsers.contains(user)) {
                return;
            }
            BigDecimal userAmount;
            BigDecimal wxAmount;
            BigDecimal manualAmount;
            // 扣除固定抽成后的动态比例
            userAmount = mode2RemainAmount.multiply(user.getRealRate()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN);
            wxAmount = mode2RemainAmount.multiply(user.getWxRate()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN);
            manualAmount = userAmount.subtract(wxAmount);
            ProfitSharingRecord record = new ProfitSharingRecord();
            record.setScenicId(scenicId);
            record.setOrderId(orderId);
            record.setUserId(user.getId());
            record.setUserName(user.getName());
            record.setAmount(userAmount);
            record.setWxAmount(wxAmount);
            record.setManualAmount(manualAmount);
            record.setRateMode(user.getRateMode());
            record.setWxRate(user.getWxRate());
            record.setRealRate(user.getRealRate());
            record.setOrderAmount(amount);
            record.setCreateTime(new Date());
            records.add(record);
            alreadyProcessedUsers.add(user);
        });
        final BigDecimal mode4RemainAmount = amount.subtract(records.stream().map(ProfitSharingRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 找出4的用户
        config.getUsers().stream().filter(user -> user.getRateMode() == 4).forEach(user -> {
            if (alreadyProcessedUsers.contains(user)) {
                return;
            }
            BigDecimal userAmount;
            BigDecimal wxAmount;
            BigDecimal manualAmount;
            // 扣除其他所有类型抽成后的动态比例
            userAmount = mode4RemainAmount.multiply(user.getRealRate()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN);
            wxAmount = mode4RemainAmount.multiply(user.getWxRate()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN);
            manualAmount = userAmount.subtract(wxAmount);
            ProfitSharingRecord record = new ProfitSharingRecord();
            record.setScenicId(scenicId);
            record.setOrderId(orderId);
            record.setUserId(user.getId());
            record.setUserName(user.getName());
            record.setAmount(userAmount);
            record.setWxAmount(wxAmount);
            record.setManualAmount(manualAmount);
            record.setRateMode(user.getRateMode());
            record.setWxRate(user.getWxRate());
            record.setRealRate(user.getRealRate());
            record.setOrderAmount(amount);
            record.setCreateTime(new Date());
            records.add(record);
            alreadyProcessedUsers.add(user);
        });
        final BigDecimal mode0RemainAmount = amount.subtract(records.stream().map(ProfitSharingRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 找出0的用户
        List<ProfitSharingUser> mode0User = config.getUsers().stream().filter(user -> user.getRateMode() == 0).collect(Collectors.toList());
        mode0User.forEach(user -> {
            if (alreadyProcessedUsers.contains(user)) {
                return;
            }
            BigDecimal userAmount;
            BigDecimal wxAmount;
            BigDecimal manualAmount;
            if (user.getRateMode() == 0) { // 剩余比例
                userAmount = mode0RemainAmount.divide(BigDecimal.valueOf(mode0User.size()), 2, RoundingMode.HALF_DOWN);
                wxAmount = BigDecimal.ZERO;
                manualAmount = userAmount.subtract(wxAmount);
            } else {
                return;
            }
            ProfitSharingRecord record = new ProfitSharingRecord();
            record.setScenicId(scenicId);
            record.setOrderId(orderId);
            record.setUserId(user.getId());
            record.setUserName(user.getName());
            record.setAmount(userAmount);
            record.setWxAmount(wxAmount);
            record.setManualAmount(manualAmount);
            record.setRateMode(user.getRateMode());
            record.setWxRate(user.getWxRate());
            record.setRealRate(user.getRealRate());
            record.setOrderAmount(amount);
            record.setCreateTime(new Date());
            records.add(record);
            alreadyProcessedUsers.add(user);
        });
        // 没有操作过的用户
        config.getUsers().stream().filter(user -> !alreadyProcessedUsers.contains(user)).forEach(user -> {
            ProfitSharingRecord record = new ProfitSharingRecord();
            record.setScenicId(scenicId);
            record.setOrderId(orderId);
            record.setUserId(user.getId());
            record.setUserName(user.getName());
            record.setAmount(BigDecimal.ZERO);
            record.setWxAmount(BigDecimal.ZERO);
            record.setManualAmount(BigDecimal.ZERO);
            record.setRateMode(user.getRateMode());
            record.setWxRate(user.getWxRate());
            record.setRealRate(user.getRealRate());
            record.setOrderAmount(amount);
            record.setCreateTime(new Date());
            records.add(record);
            alreadyProcessedUsers.add(user);
        });
        final BigDecimal remainAmount = amount.subtract(records.stream().map(ProfitSharingRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        if (remainAmount.compareTo(BigDecimal.ZERO) < 0) {
            log.error("分账剩余金额不足!!! scenicId: {}, orderId: {}, amount: {}, config: {}", scenicId, orderId, amount, config);
            return;
        }
        if (remainAmount.compareTo(BigDecimal.ZERO) > 0) {
            ProfitSharingRecord record = new ProfitSharingRecord();
            record.setScenicId(scenicId);
            record.setOrderId(orderId);
            record.setUserId(0L);
            record.setUserName("分账剩余");
            record.setRateMode(-1);
            record.setAmount(remainAmount);
            record.setWxAmount(BigDecimal.ZERO);
            record.setManualAmount(remainAmount);
            record.setWxRate(BigDecimal.ZERO);
            record.setRealRate(BigDecimal.ZERO);
            record.setOrderAmount(amount);
            record.setCreateTime(new Date());
            records.add(record);
        }
        revokeProfitSharing(scenicId, orderId, "重新分账");
        recordMapper.batchInsert(records);
    }

    public void revokeProfitSharing(Long scenicId, Long orderId, String revokeReason) {
        recordMapper.deleteByScenicIdAndOrderId(scenicId, orderId, revokeReason);
    }
}