package cn.iocoder.yudao.module.bpm.service.financialpayment;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.Constants;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.financialpayment.vo.FinancialPaymentPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.financialpayment.vo.FinancialPaymentSaveReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.financialpayment.vo.FinancialPaymentSaveVO;
import cn.iocoder.yudao.module.bpm.controller.admin.financialpaymentitem.vo.FinancialPaymentItemSaveReqVO;
import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpaymentitem.FinancialPaymentItemDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.*;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.financialpayment.FinancialPaymentMapper;
import cn.iocoder.yudao.module.bpm.dal.mysql.financialpaymentitem.FinancialPaymentItemMapper;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.*;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;

/**
 * 财务支付管理 Service 实现类
 *
 * @author 艾楷
 */
@Service
@Slf4j
@Validated
public class FinancialPaymentServiceImpl implements FinancialPaymentService {

    @Resource
    private FinancialPaymentMapper financialPaymentMapper;
    @Resource
    private FinancialPaymentItemMapper financialPaymentItemMapper;
    @Resource
    private BpmOACashMapper cashMapper;
    @Resource
    private BpmOAImprestMapper imprestMapper;
    @Resource
    private BpmOAProcurePayMapper oAProcurePayMapper;
    @Resource
    private BpmOAReimbursementMapper reimbursementMapper;
    @Resource
    private BpmOASupplierPurchasePaymentMapper supplierPurchasePaymentMapper;
    @Resource
    private SubscribeMessageSendApi subscribeMessageSendApi;
    @Resource
    private AdminUserApi userApi;
    @Resource
    private BpmProcessInstanceExtMapper processInstanceExtMapper;
    @Resource
    private DeptApi deptApi;

    @Override
    public Long createFinancialPayment(FinancialPaymentSaveVO vo) {
        FinancialPaymentItemSaveReqVO createReqVO = vo.getFinancialPaymentItemSaveReqVO();
        // 插入子表
        createReqVO.setFinancialPaymentId(vo.getId());
        FinancialPaymentItemDO financialPaymentItem = BeanUtils.toBean(createReqVO, FinancialPaymentItemDO.class);
        financialPaymentItemMapper.insert(financialPaymentItem);

        // 查询财务支付信息 - 并且更新
        FinancialPaymentDO financialPayment = this.getFinancialPayment(vo.getId());
        if (vo.getStatus() == 1) {
            financialPayment.setActualPayment(financialPayment.getActualPayment().add(financialPaymentItem.getAmount()));
            if (vo.getType() != null && vo.getType() == 1) {
                financialPayment.setStatus(2);
            } else {
                if (financialPayment.getActualPayment().compareTo(financialPayment.getAmountPayable()) >= 0) {
                    financialPayment.setStatus(2);
                } else {
                    financialPayment.setStatus(1);
                }
            }
        } else {
            // TODO: 2024/8/18  - 驳回该流程通过流程实例id 发消息通知发起人 - 更改状态
            financialPayment.setStatus(3);
            // -- 修改流程状态
            if (financialPayment.getType() == 1) {
                cashMapper.updateById(new BpmOACashDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult()));
            } else if (financialPayment.getType() == 2) {
                imprestMapper.updateById(new BpmOAImprestDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult()));
            } else if (financialPayment.getType() == 3) {
                oAProcurePayMapper.updateById(new BpmOAProcurePayDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult()));
            } else if (financialPayment.getType() == 4) {
                reimbursementMapper.updateById(new BpmOAReimbursementDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult()));
            } else if (financialPayment.getType() == 5) {
                supplierPurchasePaymentMapper.updateById(new BpmOASupplierPurchasePaymentDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult()));
            }
            BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(financialPayment.getProcessInstanceId())
                    .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
                    .setResult(BpmProcessInstanceResultEnum.BACK.getResult());
            processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
        }
        this.updateById(financialPayment);
        try {
            AdminUserRespDTO adminUserRespDTO = userApi.getUser(financialPayment.getUserId()).getData();
            if (StrUtil.isNotEmpty(adminUserRespDTO.getOpenId())) {
                String result = vo.getStatus() == 1 ? "通过" : "拒绝";
                String page = vo.getStatus() == 1 ?
                        "subPages/paymentVoucher/paymentVoucher?id=" + financialPayment.getId() :
                        "subPagesB/bpm/task/todo/examineApprove?id=" + financialPayment.getId() + "&isDetail=1";
                // --- 发消息通知发起人
                String time = financialPaymentItem.getCreateTime().format(Constants.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
                subscribeMessageSendApi.sendApprovalResultNotification(
                        BpmMessageConvert.INSTANCE.convertApprovalResultNotificationPage(
                                adminUserRespDTO.getOpenId(), financialPayment.getProcessInstanceName(), time, result, (StrUtil.isEmpty(financialPaymentItem.getNotes()) ? result : financialPaymentItem.getNotes()),
                                "formal", page));
            }
        } catch (Exception e) {
            log.error("财务管理审批发送通知人失败:{}", financialPayment);
        }
        // 返回
        return financialPayment.getId();
    }

    @Override
    public void updateFinancialPayment(FinancialPaymentSaveReqVO updateReqVO) {
        // 更新
        FinancialPaymentDO updateObj = BeanUtils.toBean(updateReqVO, FinancialPaymentDO.class);
        financialPaymentMapper.updateById(updateObj);
    }

    @Override
    public void deleteFinancialPayment(Long id) {
        // 删除
        financialPaymentMapper.deleteById(id);
    }

    @Override
    public FinancialPaymentDO getFinancialPayment(Long id) {
        return financialPaymentMapper.getFinancialPayment(id);
    }

    @Override
    public PageResult<FinancialPaymentDO> getFinancialPaymentPage(FinancialPaymentPageReqVO pageReqVO) {
        pageReqVO.setReceiveUserId(getLoginUserId());
        List<Long> deptIds = new ArrayList<>();
        if (pageReqVO.getDeptId() != null) {
            deptIds.add(pageReqVO.getDeptId());
            CommonResult<List<Long>> childDeptList = deptApi.getChildDeptList(pageReqVO.getDeptId());
            if (childDeptList.isSuccess()) {
                deptIds.addAll(childDeptList.getData());
            }
            pageReqVO.setDeptIds(deptIds);
        }
        IPage<FinancialPaymentDO> vos = financialPaymentMapper.getFinancialPaymentPage(pageReqVO, MyBatisUtils.buildPage(pageReqVO));
        return new PageResult<>(vos.getRecords(), vos.getTotal());
    }

    @Override
    public void save(FinancialPaymentDO financialPaymentDO) {
        financialPaymentMapper.insert(financialPaymentDO);
    }

    @Override
    public void receive(List<Long> ids) {
        Long userId = getLoginUserId();
        financialPaymentMapper.update(new FinancialPaymentDO().setReceiveUserId(userId), new LambdaQueryWrapper<FinancialPaymentDO>()
                .in(FinancialPaymentDO::getId, ids));
    }

    @Override
    public void updateById(FinancialPaymentDO financialPayment) {
        financialPaymentMapper.updateById(financialPayment);
    }

    @Override
    public void cancel(List<Long> ids) {
        financialPaymentMapper.cancel(ids);
    }

}
