package com.jy.business.capital.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jy.business.capital.dao.CapitalAccountDao;
import com.jy.business.capital.dao.CapitalTransactionsDao;
import com.jy.business.capital.model.dto.CapitalTransactionsDto;
import com.jy.business.capital.model.dto.CapitalTransactionsSelectDto;
import com.jy.business.capital.model.entity.CapitalTransactions;
import com.jy.business.capital.model.vo.CapitalTransactionsVo;
import com.jy.business.capital.service.CapitalTransactionsService;
import com.jy.business.contract.dao.ContractFundReceivedDao;
import com.jy.business.contract.model.entity.ContractFundReceived;
import com.jy.framework.model.constants.CommonConstant;
import com.jy.framework.utils.AssertUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 资金流水 服务实现类
 * </p>
 *
 * @author
 * @since 2024-10-16
 */
@Service
public class CapitalTransactionsServiceImpl implements CapitalTransactionsService {

    @Resource
    private CapitalTransactionsDao capitalTransactionsDao;

    @Resource
    private CapitalAccountDao capitalAccountDao;

    @Resource
    private ContractFundReceivedDao contractFundReceivedDao;

    @Override
    public Page<CapitalTransactionsVo> getPage(CapitalTransactionsSelectDto dto) {
        Page<CapitalTransactionsVo> page = capitalTransactionsDao.getPage(dto);
        List<CapitalTransactionsVo> records = page.getRecords();

        Map<Long, Date> map = new HashMap<>();
        Map<Long, BigDecimal> map2 = new HashMap<>();
        Map<Long, Long> map3 = new HashMap<>();
        records.forEach(item -> {
            map.computeIfAbsent(item.getCapitalAccountId(), k -> item.getTradingTime());
            map2.computeIfAbsent(item.getCapitalAccountId(), k -> item.getBalance());
            map3.computeIfAbsent(item.getCapitalAccountId(), k -> item.getId());
        });

        map.keySet().forEach(item -> {

            List<CapitalTransactions> list = capitalTransactionsDao.list(q -> q
                    .eq(CapitalTransactions::getCapitalAccountId, item)
                    .orderByDesc(CapitalTransactions::getTradingTime)
                    .orderByDesc(CapitalTransactions::getId)
                    .ge(CapitalTransactions::getTradingTime, map.get(item))
            );

            BigDecimal decimal = BigDecimal.ZERO;
            for (CapitalTransactions capitalTransactions : list) {
                if (capitalTransactions.getId().equals(map3.get(item))) {
                    break;
                }
                if (capitalTransactions.getType() == 0) {
                    decimal = decimal.add(capitalTransactions.getAmount());
                } else {
                    decimal = decimal.subtract(capitalTransactions.getAmount());
                }
            }

            decimal = map2.get(item).add(decimal);

            for (CapitalTransactionsVo record : records) {
                if (record.getCapitalAccountId().equals(item)) {
                    record.setDateAmount(decimal);
                    decimal = record.getType() == 0 ? decimal.add(record.getAmount()) : decimal.subtract(record.getAmount());
                }
            }

        });

        return page;
    }

    @Override
    public CapitalTransactionsVo getDetail(Long id) {
        CapitalTransactionsVo vo = capitalTransactionsDao.getDetail(id);
        AssertUtil.notNull(vo, "未知数据");
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long add(CapitalTransactionsDto dto) {
        boolean updateAmount = capitalAccountDao.updateAmount(dto.getCapitalAccountId(), dto.getType(), dto.getAmount());
        AssertUtil.eqTrue(updateAmount, "账户余额不足");

        capitalTransactionsDao.save(dto);

        if (dto.getType() == 1 && CommonConstant.YES.equals(dto.getHasContract())) {
            dto.setTargetType(70);

            ContractFundReceived contractFundReceived = new ContractFundReceived();
            contractFundReceived.setReceivedAmount(dto.getAmount());
            contractFundReceived.setCapitalAccountId(dto.getCapitalAccountId());
            contractFundReceived.setHasReceived(CommonConstant.NO);
            contractFundReceived.setReceivedTime(dto.getTradingTime());
            contractFundReceived.setCapitalTransactionsId(dto.getId());
            contractFundReceivedDao.save(contractFundReceived);
        }

        return dto.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(CapitalTransactionsDto dto) {
        CapitalTransactions oldCapitalTransactions = capitalTransactionsDao.getById(dto.getId());
        AssertUtil.notNull(oldCapitalTransactions, "未知资金流水");

        boolean updateOldAmount = capitalAccountDao.updateAmount(
                oldCapitalTransactions.getCapitalAccountId(),
                oldCapitalTransactions.getType() == 1 ? 0 : 1,
                oldCapitalTransactions.getAmount());
        AssertUtil.eqTrue(updateOldAmount, "账户余额不足");

        boolean updateAmount = capitalAccountDao.updateAmount(dto.getCapitalAccountId(), dto.getType(), dto.getAmount());
        AssertUtil.eqTrue(updateAmount, "账户余额不足");

        capitalTransactionsDao.updateById(dto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<Long> idList) {
        capitalTransactionsDao.listByIds(idList).forEach(capitalTransactions -> {
            boolean updateAmount = capitalAccountDao.updateAmount(
                    capitalTransactions.getCapitalAccountId(),
                    capitalTransactions.getType() == 0 ? 1 : 0,
                    capitalTransactions.getAmount());

            AssertUtil.eqTrue(updateAmount, "账户余额不足");
        });

        capitalTransactionsDao.removeBatchByIds(idList);
        contractFundReceivedDao.remove(q -> q
                .in(ContractFundReceived::getCapitalTransactionsId, idList));
    }

}
