package com.jwipc.finance.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.dto.ApiResult;
import com.jwipc.api.dto.OaCallBackDTO;
import com.jwipc.api.dto.PaymentCallBackDTO;
import com.jwipc.finance.dto.PayableRefundApiDTO;
import com.jwipc.finance.dto.PaymentReceiptApiDTO;
import com.jwipc.finance.dto.PaymentRecordDTO;
import com.jwipc.finance.entity.*;
import com.jwipc.finance.logic.PaymentCallBackLogic;
import com.jwipc.finance.logic.PaymentCodApplyLogic;
import com.jwipc.finance.service.*;
import com.jwipc.sys.client.FileClient;
import com.jwipc.sys.client.dto.FileResposeCDTO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author shenyang.ou
 * @date 2025/10/30 18:00
 * @desc
 */
@Service
@RequiredArgsConstructor
public class PaymentCallBackLogicImpl implements PaymentCallBackLogic {
    private final IPaymentCodApplyService paymentCodApplyService;
    private final IPaymentCodApplyDetailService paymentCodApplyDetailService;
    private final IPaymentAdvanceApplyService paymentAdvanceApplyService;
    private final IPaymentReceiptService paymentReceiptService;
    private final IPayableRefundService payableRefundService;
    private final IInvoicedApplyService invoicedApplyService;
    private final IPaymentChangeService paymentChangeService;
    private final PaymentCodApplyLogic paymentCodApplyLogic;
    private final FileClient fileClient;
    @Override
    public ApiResult callback(PaymentCallBackDTO callBackDTO) {
        PaymentCallBackDTO.ItData data = callBackDTO.getIT_DATA();
        if (StringUtils.isEmpty(data.getWorkflowId())){
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入流程id").build();
        }
        if (StringUtils.isEmpty(data.getProcessCode())){
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入流程号").build();
        }
        if (StringUtils.isEmpty(data.getType())){
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入业务类型").build();
        }
        if (null == data.getAuditState()){
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入单据整体状态").build();
        }
        if (data.getAuditState()==2&&StringUtils.isEmpty(data.getAuditMessage())){
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入审批意见").build();
        }
        if ((data.getAuditState()==5||data.getAuditState()==6)&&StringUtils.isEmpty(data.getPaymentAmount())){
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入付款金额").build();
        }
        if (data.getType().equals("201")){
            PaymentCodApply paymentCodApply = paymentCodApplyService.getOne(new LambdaQueryWrapper<PaymentCodApply>().eq(PaymentCodApply::getOaProcessId, data.getWorkflowId()).last(" limit 1"));
            if (ObjectUtil.isNull(paymentCodApply)){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("未找到对应的付款申请单").build();
            }
            if (data.getAuditState()==1){
                paymentCodApply.setStatus(3);
            } else if (data.getAuditState()==2) {
                paymentCodApply.setStatus(4);
            } else if (data.getAuditState()==3) {
                paymentCodApply.setStatus(6);
                //废弃的时候，等同删除操作，需要更新付款计划本月已请款金额，减少
                paymentCodApplyLogic.initPaymentPlanSummary(paymentCodApply,false);
            } else if (data.getAuditState()==4) {
                paymentCodApply.setStatus(7);
            } else if (data.getAuditState()==5) {
                paymentCodApply.setStatus(8);
                paymentCodApply.setOaAleradyPayMoney(new BigDecimal(data.getPaymentAmount()));
                //oa审批同意，需要更新付款计划本月已付款金额数。
                paymentCodApplyLogic.initPaymentPlanSummary(paymentCodApply, 4);
            } else if (data.getAuditState()==6) {
                paymentCodApply.setStatus(5);
                paymentCodApply.setOaAleradyPayMoney(new BigDecimal(data.getPaymentAmount()));
                //oa审批同意，需要更新付款计划本月已付款金额数。
                paymentCodApplyLogic.initPaymentPlanSummary(paymentCodApply, 4);
            }else if (data.getAuditState()==7) {
                paymentCodApply.setStatus(9);
            }
            paymentCodApply.setOaProcessMessage(data.getAuditMessage());
            paymentCodApplyService.updateById(paymentCodApply);
        }else {
            PaymentAdvanceApply paymentAdvanceApply = paymentAdvanceApplyService.getOne(new LambdaQueryWrapper<PaymentAdvanceApply>().eq(PaymentAdvanceApply::getOaProcessId, data.getWorkflowId()).last(" limit 1"));
            if (ObjectUtil.isNull(paymentAdvanceApply)){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("未找到对应的预付款申请单").build();
            }
            if (data.getAuditState()==1){
                paymentAdvanceApply.setStatus(3);
            } else if (data.getAuditState()==2) {
                paymentAdvanceApply.setStatus(4);
            } else if (data.getAuditState()==3) {
                paymentAdvanceApply.setStatus(6);
                //废弃的时候，等同删除操作，需要更新付款计划本月已请款金额，减少
                paymentAdvanceApplyService.initPaymentPlanSummary(paymentAdvanceApply,false);
            } else if (data.getAuditState()==4) {
                paymentAdvanceApply.setStatus(7);
            } else if (data.getAuditState()==5) {
                paymentAdvanceApply.setStatus(8);
                paymentAdvanceApply.setOaAleradyPayMoney(new BigDecimal(data.getPaymentAmount()));
                //oa审批同意，需要更新付款计划本月已付款金额数。
                paymentAdvanceApplyService.initPaymentPlanSummary(paymentAdvanceApply, 4);
            } else if (data.getAuditState()==6) {
                paymentAdvanceApply.setStatus(5);
                paymentAdvanceApply.setOaAleradyPayMoney(new BigDecimal(data.getPaymentAmount()));
                //oa审批同意，需要更新付款计划本月已付款金额数。
                paymentAdvanceApplyService.initPaymentPlanSummary(paymentAdvanceApply, 4);
                //查询是否有变更单
                PaymentChange paymentChange = paymentChangeService.getOne(new LambdaQueryWrapper<PaymentChange>()
                        .eq(PaymentChange::getAppNo, paymentAdvanceApply.getApApplyNo()));
                if (ObjectUtil.isNotNull(paymentChange)){
                    paymentAdvanceApply.setPaymentCompanyName(paymentChange.getPaymentCompanyName());
                    paymentAdvanceApply.setSupBankName(paymentChange.getSupBankName());
                    paymentAdvanceApply.setSupBankAccount(paymentChange.getSupBankAccount());
                    paymentAdvanceApply.setSupBankCode(paymentChange.getSupBankCode());
                    paymentAdvanceApply.setBankInterCode(paymentChange.getBankInterCode());
                    paymentAdvanceApply.setBankAddress(paymentChange.getBankAddress());
                }
            }else if (data.getAuditState()==7) {
                paymentAdvanceApply.setStatus(9);
            }
            paymentAdvanceApply.setOaAuditMessage(data.getAuditMessage());
            paymentAdvanceApplyService.updateById(paymentAdvanceApply);
        }
        return ApiResult.builder().code(RestCode.SAP_SUCCESS.getCode()).message("成功").build();
    }

    @Override
    public ApiResult paymentReceipt(PaymentReceiptApiDTO callBackDTO) {
        List<PaymentReceiptApiDTO.ItData> list = callBackDTO.getIT_ITEM();
        for (PaymentReceiptApiDTO.ItData data : list){
            if (StringUtils.isEmpty(data.getYWLX())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入业务类型").build();
            }
            if (StringUtils.isEmpty(data.getFKSQDH())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入付款申请单号").build();
            }
            if (StringUtils.isEmpty(data.getFJID())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入附件ID").build();
            }
            if (StringUtils.isEmpty(data.getFKDLS())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入回执单编号/付款单流水").build();
            }

            if (!data.getYWLX().equals("201")&& !data.getYWLX().equals("202")){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("传入的业务类型{}不正确",data.getYWLX())).build();
            }
            Long mainId = null;
            if (data.getYWLX().equals("201")){
                PaymentCodApply paymentCodApply = paymentCodApplyService.getOne(new LambdaQueryWrapper<PaymentCodApply>().eq(PaymentCodApply::getCpApplyNo, data.getFKSQDH()).eq(PaymentCodApply::getDeleteFlag, 0).last(" limit 1"));
                if (ObjectUtil.isNull(paymentCodApply)){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("未找到对应的付款申请单").build();
                }
                mainId = paymentCodApply.getId();
            }else {
                PaymentAdvanceApply paymentAdvanceApply = paymentAdvanceApplyService.getOne(new LambdaQueryWrapper<PaymentAdvanceApply>().eq(PaymentAdvanceApply::getApApplyNo, data.getFKSQDH()).eq(PaymentAdvanceApply::getDeleteFlag, 0).last(" limit 1"));
                if (ObjectUtil.isNull(paymentAdvanceApply)){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("未找到对应的预付款申请单").build();
                }
                mainId = paymentAdvanceApply.getId();
            }
            String[] fileList = data.getFJID().split(",");
            for (String fileId : fileList){
                FileResposeCDTO fileInfo = fileClient.getFileInfo(Long.valueOf(fileId));
                if (ObjectUtil.isNull(fileInfo)){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("未找到附件{}",fileId)).build();
                }
            }

            PaymentReceipt paymentReceipt = paymentReceiptService.getOne(new LambdaQueryWrapper<PaymentReceipt>()
                    .eq(PaymentReceipt::getBusinessType, data.getYWLX())
                    .eq(PaymentReceipt::getMainCode, data.getFKSQDH())
                    .eq(PaymentReceipt::getReceiptCode, data.getFKDLS())
                    .last(" limit 1"));
            if (ObjectUtil.isNull(paymentReceipt)){
                paymentReceipt = new PaymentReceipt();
                paymentReceipt.setBusinessType(Integer.valueOf(data.getYWLX()));
                paymentReceipt.setMainId(mainId);
                paymentReceipt.setMainCode(data.getFKSQDH());
                paymentReceipt.setReceiptCode(data.getFKDLS());
                paymentReceipt.setFileIds(data.getFJID());
                paymentReceipt.setCreateTime(LocalDateTime.now());
                paymentReceipt.setDeleteFlag("1".equals(data.getDEL())?1:0);
                paymentReceiptService.save(paymentReceipt);

            }else {
                paymentReceipt.setFileIds(data.getFJID());
                paymentReceipt.setDeleteFlag("1".equals(data.getDEL())?1:0);
                paymentReceipt.setUpdateTime(LocalDateTime.now());
                paymentReceiptService.updateById(paymentReceipt);
            }
        }
        return ApiResult.builder().code(RestCode.SAP_SUCCESS.getCode()).message("成功").build();
    }

    @Override
    public ApiResult payableRefund(PayableRefundApiDTO callBackDTO) {
        List<PayableRefundApiDTO.ItData> list = callBackDTO.getIT_ITEM();
        List<PayableRefund> needSave = new ArrayList<>();
        List<PayableRefund> needUpdate = new ArrayList<>();
        for (PayableRefundApiDTO.ItData data : list){
            if (StringUtils.isEmpty(data.getWYBS())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入唯一标识").build();
            }
            if (StringUtils.isEmpty(data.getYHLS())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入银行流水").build();
            }
            if (StringUtils.isEmpty(data.getTKJE())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入退款金额").build();
            }
            if (StringUtils.isEmpty(data.getBZ())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入币种").build();
            }
            String TKRI = data.getTKRI();
            if (StrUtil.isNotEmpty(TKRI)) {
                try {
                    TKRI = TKRI.replaceAll("/", "-");
                    Date codeDate = DateUtil.parse(TKRI, "yyyy-MM-dd");
                } catch (Exception e) {
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请输入正确的退款日期；如：2025-11-11").build();
                }
            }
            if (StringUtils.isEmpty(data.getTKRI())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入退款日期").build();
            }

            String CJRQ = data.getCJRQ();
            if (StrUtil.isNotEmpty(CJRQ)) {
                try {
                    CJRQ = CJRQ.replaceAll("/", "-");
                    Date codeDate = DateUtil.parse(CJRQ, "yyyy-MM-dd");
                } catch (Exception e) {
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请输入正确的创建日期；如：2025-11-11").build();
                }
            }
            if (StringUtils.isEmpty(data.getCJRQ())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入创建日期").build();
            }

            String DZDH = data.getDZDH();
            if (StrUtil.isNotEmpty(DZDH)){
                InvoicedApply invoicedApply = invoicedApplyService.getOne(new LambdaQueryWrapper<InvoicedApply>().eq(InvoicedApply::getAccountStatementNo, DZDH).eq(InvoicedApply::getDeleteFlag, 0).last(" limit 1"));
                if (ObjectUtil.isNull(invoicedApply)){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("未找到对账单号【"+DZDH+"】"+"】对应的开票申请单").build();
                }
                if (invoicedApply.getStatus()!=9||invoicedApply.getPostStatus()!=5){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("对账单号【"+DZDH+"】对应的开票申请单未过账完成").build();
                }
                PaymentCodApplyDetail paymentCodApplyDetail = paymentCodApplyDetailService.getOne(new LambdaQueryWrapper<PaymentCodApplyDetail>().eq(PaymentCodApplyDetail::getInvoiceNo, invoicedApply.getInvoiceApplyNo()).eq(PaymentCodApplyDetail::getDeleteFlag, 0).last(" limit 1"));
                if (ObjectUtil.isNotNull(paymentCodApplyDetail)){
                    PaymentCodApply paymentCodApply = paymentCodApplyService.getOne(new LambdaQueryWrapper<PaymentCodApply>().eq(PaymentCodApply::getId, paymentCodApplyDetail.getCppId()).eq(PaymentCodApply::getStatus, 6));
                    if (ObjectUtil.isNull(paymentCodApply)) {
                        return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("对账单号【"+DZDH+"】已经发起了付款申请").build();
                    }
                }
//                if (invoicedApply.getActualUnpaidAmount().compareTo(BigDecimal.ZERO)<0){
//                    invoicedApply.setActualUnpaidAmount(invoicedApply.getActualUnpaidAmount().negate());
//                }
//                if (invoicedApply.getActualUnpaidAmount().stripTrailingZeros().compareTo(new BigDecimal(data.getTKJE()).stripTrailingZeros())!=0){
//                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("对账单号【"+DZDH+"】对应的开票申请单实际未付金额与退款金额不一致，只允许整单退款").build();
//                }
            }else {
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入对账单号").build();
            }

            if (StringUtils.isEmpty(data.getQXSK())){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入取消收款").build();
            }
            PayableRefund paymentReceipt = payableRefundService.getOne(new LambdaQueryWrapper<PayableRefund>().eq(PayableRefund::getSkdh, data.getSKDH()).eq(PayableRefund::getDzdh, data.getDZDH()).last(" limit 1"));
            if (ObjectUtil.isNull(paymentReceipt)){
                paymentReceipt = new PayableRefund();
                paymentReceipt.setWybs(data.getWYBS());
                paymentReceipt.setDzdh(data.getDZDH());
                paymentReceipt.setYhls(data.getYHLS());
                paymentReceipt.setSkdh(data.getSKDH());
                paymentReceipt.setTkje(data.getTKJE());
                paymentReceipt.setBz(data.getBZ());
                paymentReceipt.setQxsk(data.getQXSK());
                Date codeDate = DateUtil.parse(TKRI, "yyyy-MM-dd");
                paymentReceipt.setTkri(LocalDateTimeUtil.parse(DateUtil.format(codeDate,"yyyy-MM-dd"), "yyyy-MM-dd"));

                Date codeDate1 = DateUtil.parse(TKRI, "yyyy-MM-dd");
                paymentReceipt.setCjrq(LocalDateTimeUtil.parse(DateUtil.format(codeDate1,"yyyy-MM-dd"), "yyyy-MM-dd"));
                paymentReceipt.setCreateTime(LocalDateTime.now());
//                payableRefundService.save(paymentReceipt);
                needSave.add(paymentReceipt);

            }else {
                paymentReceipt.setWybs(data.getWYBS());
                paymentReceipt.setDzdh(data.getDZDH());
                paymentReceipt.setYhls(data.getYHLS());
                paymentReceipt.setSkdh(data.getSKDH());
                paymentReceipt.setTkje(data.getTKJE());
                paymentReceipt.setBz(data.getBZ());
                paymentReceipt.setQxsk(data.getQXSK());
                Date codeDate = DateUtil.parse(TKRI, "yyyy-MM-dd");
                paymentReceipt.setTkri(LocalDateTimeUtil.parse(DateUtil.format(codeDate,"yyyy-MM-dd"), "yyyy-MM-dd"));
                Date codeDate1 = DateUtil.parse(TKRI, "yyyy-MM-dd");
                paymentReceipt.setCjrq(LocalDateTimeUtil.parse(DateUtil.format(codeDate1,"yyyy-MM-dd"), "yyyy-MM-dd"));
                paymentReceipt.setUpdateTime(LocalDateTime.now());
//                payableRefundService.updateById(paymentReceipt);
                needUpdate.add(paymentReceipt);
            }

        }

        //list根据YHLS做分组，不是查询
        Map<String, List<PayableRefundApiDTO.ItData>> map = list.stream().collect(Collectors.groupingBy(PayableRefundApiDTO.ItData::getYHLS));
        for (Map.Entry<String, List<PayableRefundApiDTO.ItData>> entry : map.entrySet()) {
            String key = entry.getKey();
            List<PayableRefundApiDTO.ItData> dtos = entry.getValue();
            BigDecimal actualUnpaidAmount = new BigDecimal("0");
            for (PayableRefundApiDTO.ItData dto : dtos) {
                InvoicedApply invoicedApply = invoicedApplyService.getOne(new LambdaQueryWrapper<InvoicedApply>().eq(InvoicedApply::getAccountStatementNo, dto.getDZDH()).eq(InvoicedApply::getDeleteFlag, 0).last(" limit 1"));
                actualUnpaidAmount = actualUnpaidAmount.add(invoicedApply.getActualUnpaidAmount());
            }

            BigDecimal tkje = new BigDecimal(dtos.get(0).getTKJE());
            if (tkje.compareTo(BigDecimal.ZERO)>0){
                tkje = tkje.negate();
            }
            if (actualUnpaidAmount.compareTo(tkje)!=0){
                return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("银行流水号【"+key+"】退款金额【"+tkje+"】与累计的实际未付金额【"+actualUnpaidAmount+"】不一致").build();
            }
        }
        if (CollUtil.isNotEmpty(needSave)){
            payableRefundService.saveBatch(needSave);
        }
        if (CollUtil.isNotEmpty(needUpdate)){
            payableRefundService.updateBatchById(needUpdate);
        }
        return ApiResult.builder().code(RestCode.SAP_SUCCESS.getCode()).message("成功").build();
    }
}
