package com.fjhx.account.service.account.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.account.entity.account.dto.AccountPaymentDto;
import com.fjhx.account.entity.account.dto.AccountRequestFundsSelectDto;
import com.fjhx.account.entity.account.enums.PaymentStatusEnum;
import com.fjhx.account.entity.account.po.*;
import com.fjhx.account.entity.account.vo.AccountPaymentRecordsVo;
import com.fjhx.account.entity.account.vo.AccountPaymentVo;
import com.fjhx.account.mapper.account.AccountPaymentMapper;
import com.fjhx.account.service.account.*;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.common.service.corporation.CorporationService;
import com.fjhx.common.utils.Assert;
import com.fjhx.file.utils.ObsFileUtil;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * <p>
 * 打款表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-11
 */
@Service
public class AccountPaymentServiceImpl extends ServiceImpl<AccountPaymentMapper, AccountPayment> implements AccountPaymentService {
    @Autowired
    private CorporationService corporationService;

    @Autowired
    private ISysDeptService sysDeptService;

    @Autowired
    private AccountRemainderService accountRemainderService;

    @Autowired
    private AccountRunningWaterService accountRunningWaterService;

    @Autowired
    private AccountManagementService accountManagementService;

    @Autowired
    private AccountPaymentRecordsService accountPaymentRecordsService;

    @Override
    public Page<AccountPaymentVo> getPage(AccountRequestFundsSelectDto dto) {

        QueryWrapper<Object> wrapper = Wrappers.query();

        wrapper.like(ObjectUtil.isNotEmpty(dto.getKeyword()), "ap.payment_remark", dto.getKeyword());

        // 归属公司
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getCorporationId()), "ap.corporation_id", dto.getCorporationId());
        // 归属部门
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getDepartmentId()), "ap.department_id", dto.getDepartmentId());
        // 申请人
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getCreateUser()), "ap.data_user", dto.getCreateUser());
        // 打款类型
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getType()), "ap.type", dto.getType());
        // 请款时间
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getBeginCreateTime()), "ap.create_time", dto.getBeginCreateTime());
        wrapper.le(ObjectUtil.isNotEmpty(dto.getEndCreateTime()), "ap.create_time", dto.getEndCreateTime());
        // 用款时间
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getBeginTime()), "ap.payment_time", dto.getBeginTime());
        wrapper.le(ObjectUtil.isNotEmpty(dto.getEndTime()), "ap.payment_time", dto.getEndTime());
        // 币种
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getCurrency()), "ap.currency", dto.getCurrency());
        // 交易金额
        wrapper.ge(ObjectUtil.isNotEmpty(dto.getStartAmount()), "ap.amount", dto.getStartAmount());
        wrapper.le(ObjectUtil.isNotEmpty(dto.getEndAmount()), "ap.amount", dto.getEndAmount());
        // 付款状态
        wrapper.eq(ObjectUtil.isNotEmpty(dto.getPaymentStatus()), "ap.status", dto.getPaymentStatus());
        // 款项说明
        wrapper.like(ObjectUtil.isNotEmpty(dto.getPaymentRemark()), "ap.payment_remark", dto.getPaymentRemark());

        wrapper.orderByDesc("ap.status", "ap.payment_time", "ap.create_time");

        //对方账户过滤
        wrapper.like(ObjectUtil.isNotEmpty(dto.getOppositeAccountName()), "ap.name", dto.getOppositeAccountName());

        Page<AccountPaymentVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<AccountPaymentVo> records = page.getRecords();
        if (records.size() == 0) {
            return page;
        }

        // 赋值公司名称信息
        corporationService.attributeAssign(records, AccountPaymentVo::getCorporationId, (item, corporation) -> {
            item.setCorporationName(corporation.getName());
        });

        // 赋值用户名称
        UserUtil.assignmentNickName(records, AccountPayment::getDataUser, AccountPaymentVo::setUserName);

        // 赋值部门名称
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        List<Long> deptIdList = records.stream()
                .map(AccountPaymentVo::getDepartmentId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(deptIdList)) {
            List<SysDept> sysDeptList = sysDeptService.listByIds(deptIdList);
            Map<Long, String> deptMap = sysDeptList.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));
            records.forEach(item -> item.setDeptName(deptMap.get(item.getDepartmentId())));
        }
        DynamicDataSourceContextHolder.poll();

        return page;
    }

    /**
     * 打款表明细
     */
    @Override
    public AccountPaymentVo detail(Long id) {
        AccountPayment AccountPayment = baseMapper.detail(id);
        AccountPaymentVo result = BeanUtil.toBean(AccountPayment, AccountPaymentVo.class);

        if (ObjectUtil.isNotEmpty(result.getAccountManagementId())) {
            //查询实际打款的付款账户名称；
            AccountManagement accountManagement = accountManagementService.getById(result.getAccountManagementId());
            if (ObjectUtil.isNotEmpty(accountManagement)) {
                result.setAccountManagementName(accountManagement.getName());
            }

        }

        if (ObjectUtil.isNotEmpty(result.getBusinessManagementId())) {
            //查询业务中选中的付款账户名称；
            AccountManagement accountManagement = accountManagementService.getById(result.getBusinessManagementId());
            if (ObjectUtil.isNotEmpty(accountManagement)) {
                result.setBusinessManagementName(accountManagement.getName());
            }

        }

        //赋值打款记录
        List<AccountPaymentRecords> accountPaymentRecordsList = accountPaymentRecordsService.list(q -> q
                .eq(AccountPaymentRecords::getAccountPaymentId, id)
                .orderByAsc(BasePo::getCreateTime)
        );
        List<AccountPaymentRecordsVo> accountPaymentRecordsVos = BeanUtil.copyToList(accountPaymentRecordsList, AccountPaymentRecordsVo.class);
        result.setAccountPaymentRecordsList(accountPaymentRecordsVos);

        return result;
    }

    /**
     * 打款功能
     *
     * @param accountPaymentDto
     */
    @Override
    @DSTransactional
    public void add(AccountPaymentDto accountPaymentDto) {
        Assert.notEmpty(accountPaymentDto.getId(), "打款id不能为空");

        AccountRemainder accountRemainder = accountRemainderService.getOne(Wrappers.<AccountRemainder>lambdaQuery()
                .eq(AccountRemainder::getAccountManagementId, accountPaymentDto.getAccountManagementId())
                .eq(AccountRemainder::getCurrency, accountPaymentDto.getCurrency()));

        // 如果不存在这条数据则返回账户余额不足
        if (ObjectUtil.isEmpty(accountRemainder)) {
            throw new ServiceException("该账户不存在此币种，请前往资金账户添加");
        }

        // 如果余额小于付款金额则返回账户余额不足
        if (accountRemainder.getRemainder().compareTo(accountPaymentDto.getAmount()) < 0) {
            throw new ServiceException("账户余额不足");
        }

        //刷新打款信息
        AccountPayment oldAccountPayment = this.getById(accountPaymentDto.getId());
        //如果是未打款把已打款金额改成0（修复旧数据）
        if (oldAccountPayment.getStatus().equals(PaymentStatusEnum.UNDER_REVIEW.getKey())) {
            oldAccountPayment.setAmount(BigDecimal.ZERO);
        }
        BigDecimal add = oldAccountPayment.getAmount().add(accountPaymentDto.getAmount());
        if (add.compareTo(oldAccountPayment.getIncomeAmount()) > 0) {
            throw new ServiceException("打款金额不能大于待打款金额");
        }
        //修改打款状态
        if (add.compareTo(oldAccountPayment.getIncomeAmount()) >= 0) {
            oldAccountPayment.setStatus(PaymentStatusEnum.REJECT.getKey());
        } else {
            oldAccountPayment.setStatus(PaymentStatusEnum.PARTIAL.getKey());
        }
        //赋值已打款金额
        oldAccountPayment.setAmount(add);
        //赋值最后一次打款时间
        oldAccountPayment.setExpensesTime(accountPaymentDto.getExpensesTime());
        updateById(oldAccountPayment);

        //创建打款记录
        AccountPaymentRecords accountPaymentRecords = new AccountPaymentRecords();
        accountPaymentRecords.setAccountPaymentId(accountPaymentDto.getId());
        accountPaymentRecords.setAmount(accountPaymentDto.getAmount());

        accountPaymentRecords.setAccountManagementId(accountPaymentDto.getAccountManagementId());
        accountPaymentRecords.setCurrency(accountPaymentDto.getCurrency());
        accountPaymentRecords.setExpensesTime(accountPaymentDto.getExpensesTime());
        accountPaymentRecords.setRemark(accountPaymentDto.getRemark());
        accountPaymentRecordsService.save(accountPaymentRecords);

        // 赋值变更金额
        accountRemainder.setChangeRemainder(accountPaymentDto.getAmount());
        // 修改账户-余额表的中余额
        accountRemainder.setRemainder(accountRemainder.getRemainder().subtract(accountPaymentDto.getAmount()));
        // 打款的交易状态都是支出
        accountRemainder.setStatus("20");
        accountRemainderService.updateById(accountRemainder);

        // 添加附件信息
        ObsFileUtil.saveFile(accountPaymentDto.getFileList(), accountPaymentRecords.getId());

        // 添加资金流水表的数据
        addAccountRunningWater(accountPaymentDto, accountPaymentRecords);
    }

    @Override
    public void edit(AccountPaymentDto accountPaymentDto) {
        this.updateById(accountPaymentDto);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    /**
     * 添加资金流水表的数据
     */
    private void addAccountRunningWater(AccountPaymentDto accountPaymentDto, AccountPaymentRecords accountPaymentRecords) {

        AccountRunningWater accountRunningWater = new AccountRunningWater();
        accountRunningWater.setAccountManagementId(accountPaymentRecords.getAccountManagementId());
        //打款的状态都是支出
        accountRunningWater.setStatus("20");
        accountRunningWater.setAmount(accountPaymentRecords.getAmount());
        accountRunningWater.setCurrency(accountPaymentRecords.getCurrency());
        accountRunningWater.setOpeningBank(accountPaymentDto.getOpeningBank());
        accountRunningWater.setAccountOpening(accountPaymentDto.getAccountOpening());
        accountRunningWater.setName(accountPaymentDto.getName());
        accountRunningWater.setTransactionTime(accountPaymentRecords.getExpensesTime());
        accountRunningWater.setRemarks(accountPaymentRecords.getRemark());
        accountRunningWater.setBusinessId(accountPaymentDto.getId());
        accountRunningWater.setAccountPaymentRecordsId(accountPaymentRecords.getId());
        //添加流水类型
        accountRunningWater.setType("10");
        accountRunningWaterService.save(accountRunningWater);

    }


}
