package com.leromro.core.service.impl;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.Participant;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leromro.common.core.domain.R;
import com.leromro.common.core.domain.entity.SysUser;
import com.leromro.common.utils.SecurityUtils;
import com.leromro.core.domain.VolunteerAccount;
import com.leromro.core.domain.VolunteerTakeRecord;
import com.leromro.core.domain.dto.AddPaymentRecordDTO;
import com.leromro.core.domain.dto.WithdrawPaymentDTO;
import com.leromro.core.domain.vo.AlipayCashWithdrawal;
import com.leromro.core.mapper.VolunteerPaymentRecordsMapper;
import com.leromro.common.utils.DateUtils;
import com.leromro.core.service.IVolunteerAccountService;
import com.leromro.core.service.IVolunteerTakeRecordService;
import com.leromro.core.utils.NoUtil;
import com.leromro.core.utils.SendSmsUtil;
import com.leromro.framework.config.ConstantsConfig;
import com.leromro.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.leromro.core.mapper.VolunteerPaymentRecordsMapper;
import com.leromro.core.domain.VolunteerPaymentRecords;
import com.leromro.core.service.IVolunteerPaymentRecordsService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 志愿者打款单记录Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-05-15
 */
@Slf4j
@Service
public class VolunteerPaymentRecordsServiceImpl extends ServiceImpl<VolunteerPaymentRecordsMapper, VolunteerPaymentRecords> implements IVolunteerPaymentRecordsService
{
    @Autowired
    private VolunteerPaymentRecordsMapper volunteerPaymentRecordsMapper;

    @Autowired
    private IVolunteerTakeRecordService takeRecordService;

    @Autowired
    private IVolunteerAccountService volunteerAccountService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    @Qualifier("aliPayService")
    private AlipayClient alipayClient;

    /**
     * 查询志愿者打款单记录
     * 
     * @param volunteerPaymentRecordsId 志愿者打款单记录主键
     * @return 志愿者打款单记录
     */
    @Override
    public VolunteerPaymentRecords selectVolunteerPaymentRecordsByVolunteerPaymentRecordsId(Long volunteerPaymentRecordsId)
    {
        return volunteerPaymentRecordsMapper.selectVolunteerPaymentRecordsByVolunteerPaymentRecordsId(volunteerPaymentRecordsId);
    }

    /**
     * 查询志愿者打款单记录列表
     * 
     * @param volunteerPaymentRecords 志愿者打款单记录
     * @return 志愿者打款单记录
     */
    @Override
    public List<VolunteerPaymentRecords> selectVolunteerPaymentRecordsList(VolunteerPaymentRecords volunteerPaymentRecords)
    {
        return volunteerPaymentRecordsMapper.selectVolunteerPaymentRecordsList(volunteerPaymentRecords);
    }

    /**
     * 新增志愿者打款单记录
     * 
     * @param volunteerPaymentRecords 志愿者打款单记录
     * @return 结果
     */
    @Override
    public Boolean insertVolunteerPaymentRecords(VolunteerPaymentRecords volunteerPaymentRecords)
    {
        return this.save(volunteerPaymentRecords);
    }

    /**
     * 修改志愿者打款单记录
     * 
     * @param volunteerPaymentRecords 志愿者打款单记录
     * @return 结果
     */
    @Override
    public Boolean updateVolunteerPaymentRecords(VolunteerPaymentRecords volunteerPaymentRecords)
    {
        return this.updateById(volunteerPaymentRecords);
    }

    /**
     * 批量删除志愿者打款单记录
     * 
     * @param volunteerPaymentRecordsIds 需要删除的志愿者打款单记录主键
     * @return 结果
     */
    @Override
    public int deleteVolunteerPaymentRecordsByVolunteerPaymentRecordsIds(Long[] volunteerPaymentRecordsIds)
    {
        return volunteerPaymentRecordsMapper.deleteVolunteerPaymentRecordsByVolunteerPaymentRecordsIds(volunteerPaymentRecordsIds);
    }

    /**
     * 删除志愿者打款单记录信息
     * 
     * @param volunteerPaymentRecordsId 志愿者打款单记录主键
     * @return 结果
     */
    @Override
    public int deleteVolunteerPaymentRecordsByVolunteerPaymentRecordsId(Long volunteerPaymentRecordsId)
    {
        return volunteerPaymentRecordsMapper.deleteVolunteerPaymentRecordsByVolunteerPaymentRecordsId(volunteerPaymentRecordsId);
    }

    /**
     * 创建志愿者打款单
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public R addPaymentRecord(AddPaymentRecordDTO dto) {
        BigDecimal totalPaymentAmount = BigDecimal.ZERO;
        BigDecimal actualPaymentAmount = BigDecimal.ZERO;
        //获取所有打款单
        List<VolunteerTakeRecord> records = takeRecordService.listByIds(dto.getIds());
        //判断打款状态,并统计总金额
        for (VolunteerTakeRecord record : records) {
            if (!dto.getPayType().equals(record.getPayType())){
                return R.fail("提现申请单"+record.getTakeSn()+"打款类型不一致");
            }
            if (!"2".equals(record.getAppStatus())){
                return R.fail("提现申请单"+record.getTakeSn()+"审批状态错误");
            }
            totalPaymentAmount = totalPaymentAmount.add(record.getTakeAmount());
            actualPaymentAmount = actualPaymentAmount.add(record.getShoudAmount());
        }
        VolunteerPaymentRecords paymentRecords = new VolunteerPaymentRecords();
        paymentRecords.setPaymentOrderNumber(NoUtil.getTakeMoneyNo());
        paymentRecords.setTotalPaymentAmount(totalPaymentAmount);
        paymentRecords.setActualPaymentAmount(actualPaymentAmount);
        paymentRecords.setPayType(dto.getPayType());
        this.save(paymentRecords);
        //批量修改提现申请单，设置打款单id
        takeRecordService.update(new LambdaUpdateWrapper<VolunteerTakeRecord>()
                .set(VolunteerTakeRecord::getPaymentRecordId, paymentRecords.getVolunteerPaymentRecordsId())
                .in(VolunteerTakeRecord::getVolunteerTakeRecordId, dto.getIds()));
        return R.ok();
    }

    @Async("threadPoolTaskExecutor")
    @Override
    public void asyncPayment(Long volunteerPaymentRecordsId) {
        //查询打款单对应的申请单信息
        List<VolunteerTakeRecord> beforeRecords = takeRecordService.list(new LambdaQueryWrapper<VolunteerTakeRecord>()
                .eq(VolunteerTakeRecord::getPaymentRecordId, volunteerPaymentRecordsId));
        //循环打款
        for (VolunteerTakeRecord record : beforeRecords) {
            takeAmountByAlipay(record);
        }
        //再次查询所有申请单，判断是否已经全部打款，全部打款金额
        List<VolunteerTakeRecord> afterRecords = takeRecordService.list(new LambdaQueryWrapper<VolunteerTakeRecord>()
                .eq(VolunteerTakeRecord::getPaymentRecordId, volunteerPaymentRecordsId));
        VolunteerPaymentRecords drvPaymentRecords = new VolunteerPaymentRecords();
        drvPaymentRecords.setVolunteerPaymentRecordsId(volunteerPaymentRecordsId);
        int total = afterRecords.size();
        long prepareNum = afterRecords.stream().filter(record -> {
            return "0".equals(record.getIsPay());
        }).count();
        long successNum = afterRecords.stream().filter(record2 -> {
            return "1".equals(record2.getIsPay());
        }).count();
        long failedNum = afterRecords.stream().filter(record3 -> {
            return "2".equals(record3.getIsPay());
        }).count();

        if (total == prepareNum) {
            drvPaymentRecords.setPaymentStatus("1");
        } else if (total == successNum) {
            drvPaymentRecords.setPaymentStatus("2");
        } else if (total > successNum + failedNum) {
            drvPaymentRecords.setPaymentStatus("3");
        } else if (total == failedNum) {
            drvPaymentRecords.setPaymentStatus("4");
        }

        BigDecimal successAmount = (BigDecimal) afterRecords.stream().filter(v -> {
            return "1".equals(v.getIsPay());
        }).map(VolunteerTakeRecord::getShoudAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal failedAmount = (BigDecimal) afterRecords.stream().filter(v2 -> {
            return "2".equals(v2.getIsPay());
        }).map(VolunteerTakeRecord::getShoudAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        drvPaymentRecords.setSuccessfulPaymentAmount(successAmount);
        drvPaymentRecords.setFailedPaymentAmount(failedAmount);
        this.updateById(drvPaymentRecords);
    }

    private void takeAmountByAlipay(VolunteerTakeRecord takeAmountRecord) {
        AlipayCashWithdrawal withdrawal = new AlipayCashWithdrawal();
        withdrawal.setIdentity(takeAmountRecord.getAlipayAccountNo());
        withdrawal.setName(takeAmountRecord.getAlipayName());
        withdrawal.setTransAmount(takeAmountRecord.getShoudAmount().toString());
        withdrawal.setOutBizNo(takeAmountRecord.getTakeSn());
        withdrawal.setRemark("提现");
        withdrawal.setOrderTitle("提现转账");
        try {
            AlipayFundTransUniTransferResponse response = this.alipayCashWithdrawal(withdrawal);
            if (response.isSuccess()) {
                System.out.println("========提现转账调用成功========");
                //修改账户提现中的金额
                VolunteerAccount driverAccount = volunteerAccountService.getById(takeAmountRecord.getVolunteerAccountId());
                BigDecimal subtract = driverAccount.getBeBalance().subtract(takeAmountRecord.getTakeAmount());
                driverAccount.setBeBalance(subtract.compareTo(BigDecimal.ZERO) < 0 ? new BigDecimal(BigInteger.ZERO) : subtract);
                volunteerAccountService.updateById(driverAccount);

                //修改提现申请单状态
                takeAmountRecord.setIsPay("1");
                takeAmountRecord.setPayTime(new Date());
                takeAmountRecord.setReceiveAmount(takeAmountRecord.getShoudAmount());
                this.takeRecordService.updateById(takeAmountRecord);

                SysUser user = userService.getById(takeAmountRecord.getVolunteerUserId());
                JSONObject json = new JSONObject();
                json.putOnce("time", DateUtil.format(takeAmountRecord.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
                SendSmsUtil.send(user.getPhonenumber(), json.toString(), ConstantsConfig.SMS_TEMPLATE_TYPE_VOLUNTEER_WITGDRAW.getValue());

            } else {
                //修改账户提现中的金额,把当前申请单金额加到账户余额中，把提现申请单金额从账户提现中的金额中减去
                VolunteerAccount driverAccount = volunteerAccountService.getById(takeAmountRecord.getVolunteerAccountId());
                BigDecimal subtract = driverAccount.getBeBalance().subtract(takeAmountRecord.getTakeAmount());
                driverAccount.setBeBalance(subtract.compareTo(BigDecimal.ZERO) < 0 ? new BigDecimal(BigInteger.ZERO) : subtract);
                driverAccount.setBalance(driverAccount.getBalance().add(takeAmountRecord.getTakeAmount()));
                volunteerAccountService.updateById(driverAccount);

                takeAmountRecord.setIsPay("2");
                takeAmountRecord.setUpdateTime(new Date());
                takeAmountRecord.setPayNote(response.getSubMsg());
                this.takeRecordService.updateById(takeAmountRecord);
                log.error("支付宝转账失败：{}", response.getSubMsg());
            }
        } catch (Exception e) {
            log.error("支付宝转账调用失败：{}", e.getMessage());
        }
    }

    public AlipayFundTransUniTransferResponse alipayCashWithdrawal(AlipayCashWithdrawal vo) throws AlipayApiException {
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
        model.setOutBizNo(vo.getOutBizNo());
        model.setRemark(vo.getRemark());
        model.setBusinessParams("{\"payer_show_name_use_alias\":\"true\"}");
        model.setBizScene("DIRECT_TRANSFER");
        Participant payeeInfo = new Participant();
        payeeInfo.setIdentity(vo.getIdentity());
        payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
        payeeInfo.setName(vo.getName());
        model.setPayeeInfo(payeeInfo);
        model.setTransAmount(vo.getTransAmount());
        model.setProductCode("TRANS_ACCOUNT_NO_PWD");
        model.setOrderTitle(vo.getOrderTitle());
        request.setBizModel(model);
        AlipayFundTransUniTransferResponse response = (AlipayFundTransUniTransferResponse) this.alipayClient.certificateExecute(request);
        System.out.println("支付宝提现返回体：" + response.getBody());
        System.out.println("支付宝提现返回参数：" + JSONUtil.parseObj(response));
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }
        return response;
    }

}
