package com.ruoyi.hywz.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
//import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.hywz.common.enums.InvoiceNodeEnum;
import com.ruoyi.hywz.common.enums.MsgTemplateEnum;
import com.ruoyi.hywz.entity.AdsMatHyxtInvoiceApplyD;
import com.ruoyi.hywz.entity.AdsMatHyxtInvoiceD;
import com.ruoyi.hywz.entity.po.InvoiceApplyDetailPO;
import com.ruoyi.hywz.entity.po.InvoiceApplyPO;
import com.ruoyi.hywz.mapper.AdsMatHyxtInvoiceApplyDMapper;
import com.ruoyi.hywz.service.*;
import com.ruoyi.hywz.utils.AppNoGenUtil;
import com.ruoyi.hywz.utils.IdGen;
import com.ruoyi.system.service.ISysUserService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 发票申请单据表 服务实现类
 * </p>
 *
 * @author mybatisplus-generator
 * @date 2024-04-08 17:32:06
 */
@Service
public class AdsMatHyxtInvoiceApplyDServiceImpl extends ServiceImpl<AdsMatHyxtInvoiceApplyDMapper, AdsMatHyxtInvoiceApplyD> implements IAdsMatHyxtInvoiceApplyDService {

    @Autowired
    private ISysUserService userService;
    @Autowired
    private IAdsMatHyxtTaskRunDService adsMatHyxtTaskRunDService;
    @Autowired
    private IAdsMatHyxtTaskHistoryDService adsMatHyxtTaskHistoryDService;
    @Autowired
    private IAdsMatHyxtInvoiceDService adsMatHyxtInvoiceDService;
    @Autowired
    private IAdsMatHyxtInvoiceFileDService adsMatHyxtInvoiceFileDService;
    @Autowired
    private IAdsMatHyxtIAppService adsMatHyxtIAppService;

    /**
     * 申请单保存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applySave(InvoiceApplyPO param) {
        List<AdsMatHyxtInvoiceD> list = param.getList();
        AdsMatHyxtInvoiceApplyD applyD = null;
        // 判断新增还是修改
        if (StringUtils.isNotBlank(param.getId())) {
            applyD = this.getById(param.getId());
        }

        Date date = new Date();
        LoginUser loginUser = SecurityUtils.getLoginUser();

        if (null != applyD) {
            // 修改
            applyD.setInvoiceNum(param.getList().size());
            applyD.setUpdateTime(date);
            applyD.setCurrentNode(InvoiceNodeEnum.NODE_0.getNode());
            applyD.setNodeLabel(InvoiceNodeEnum.NODE_0.getDesc());
            this.updateById(applyD);
            this.updateBatch(loginUser, applyD, list);
        } else {
            // 新增
            this.addBatch(loginUser, list);
        }
    }

    private void addBatch(LoginUser loginUser, List<AdsMatHyxtInvoiceD> list) {
        Map<String, List<AdsMatHyxtInvoiceD>> map = new HashMap<>();
        List<AdsMatHyxtInvoiceD> nullBatchNoList = new ArrayList<>();

        // 相同批次号生成批次
        for (AdsMatHyxtInvoiceD invoiceD : list) {
            if (StringUtils.isNotBlank(invoiceD.getBatchNo())) {
                List<AdsMatHyxtInvoiceD> invoiceDS = map.get(invoiceD.getBatchNo());
                if (ObjectUtils.isEmpty(invoiceDS)) {
                    invoiceDS = new ArrayList<>();
                }
                invoiceDS.add(invoiceD);
                map.put(invoiceD.getBatchNo(), invoiceDS);
            } else {
                nullBatchNoList.add(invoiceD);
            }
        }

        Date date = new Date();
        for (String key : map.keySet()) {
            List<AdsMatHyxtInvoiceD> valueList = map.get(key);
            this.generateBatch(loginUser, date, valueList);
        }

        if (!nullBatchNoList.isEmpty()) {
            this.generateBatch(loginUser, date, nullBatchNoList);
        }
    }

    public void generateBatch(LoginUser loginUser, Date date, List<AdsMatHyxtInvoiceD> list) {
        AdsMatHyxtInvoiceApplyD applyD = new AdsMatHyxtInvoiceApplyD();
        applyD.setId(IdGen.get32UUID());
        applyD.setAppNo(AppNoGenUtil.getAppNo());
        applyD.setCurrentNode(InvoiceNodeEnum.NODE_0.getNode());
        applyD.setNodeLabel(InvoiceNodeEnum.NODE_0.getDesc());
        applyD.setCreateTime(date);
        applyD.setInvoiceNum(list.size());
        applyD.setCreateUserId(loginUser.getUser().getUserId());
        applyD.setCreateUser(loginUser.getUser().getUserName());
        applyD.setCreateUserName(loginUser.getUser().getNickName());
        applyD.setCreateUserOrgNo(loginUser.getOrgNo());
        applyD.setCreateUserOrgName(loginUser.getOrgName());
        this.save(applyD);

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String applyDate = format.format(date);

        for (AdsMatHyxtInvoiceD invoiceD : list) {
            invoiceD.setId(IdGen.get32UUID());
            invoiceD.setApplyId(applyD.getId());
            invoiceD.setStatus(0);
            invoiceD.setApplyDate(applyDate);
            invoiceD.setCreateUserId(loginUser.getUser().getUserId());
            invoiceD.setCreateUser(loginUser.getUser().getUserName());
            invoiceD.setCreateUserName(loginUser.getUser().getNickName());
            invoiceD.setCreateTime(date);
        }
        adsMatHyxtInvoiceDService.saveBatch(list);
    }

    private void updateBatch(LoginUser loginUser, AdsMatHyxtInvoiceApplyD applyD, List<AdsMatHyxtInvoiceD> list) {
        // 先删除发票，再新增
        adsMatHyxtInvoiceDService.logicDelete(applyD.getId());
        for (AdsMatHyxtInvoiceD invoiceD : list) {
            invoiceD.setId(IdGen.get32UUID());
            invoiceD.setApplyId(applyD.getId());
            invoiceD.setStatus(0);
            invoiceD.setCreateUserId(loginUser.getUser().getUserId());
            invoiceD.setCreateUser(loginUser.getUser().getUserName());
            invoiceD.setCreateUserName(loginUser.getUser().getNickName());
            invoiceD.setCreateTime(new Date());
        }
        adsMatHyxtInvoiceDService.saveBatch(list);
    }

    /**
     * 提交审核
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized R commitAudit(InvoiceApplyDetailPO param) {
        // 1.校验【单据表是否存在、是否已经提交，避免重复提交】
        SysUser sysUser = userService.selectUserByUserName(param.getAuditUser1());
        if (ObjectUtils.isEmpty(sysUser)) {
            return R.fail("审核人员不存在！");
        }

        List<String> ids = param.getIds();
        List<AdsMatHyxtInvoiceApplyD> applyDList = new ArrayList<>();
        for (String id : ids) {
            AdsMatHyxtInvoiceApplyD applyD = this.getById(id);
            if (ObjectUtils.isEmpty(applyD)) {
                return R.fail("【"+id+"】申请单据不存在！");
            }
            if (applyD.getStatus() == 1) {
                return R.fail("申请单号【"+applyD.getAppNo()+"】已提交申请，请勿重复提交！");
            }
            applyDList.add(applyD);
        }

        Date date = new Date();
        // 2.更新单据表【审核人、审核时间】
        LambdaUpdateWrapper<AdsMatHyxtInvoiceApplyD> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.in(AdsMatHyxtInvoiceApplyD::getId, ids);
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getStatus, 1);
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getAuditUser1, param.getAuditUser1());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCommitAuditTime, date);
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentNode, InvoiceNodeEnum.NODE_2.getNode());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getNodeLabel, InvoiceNodeEnum.NODE_2.getDesc());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentAuditUser, sysUser.getUserName());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentAuditUserName, sysUser.getNickName());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentAuditUserPhone, sysUser.getPhonenumber());
        this.update(updateWrapper);

        for (AdsMatHyxtInvoiceApplyD applyD : applyDList) {
            // 3.创建任务
            adsMatHyxtTaskRunDService.createInvoiceTask(applyD, sysUser);

            // 4.i国网提醒
            adsMatHyxtIAppService.sendApp(
                    applyD.getId(),
                    MsgTemplateEnum.TMP_1.getMsg(sysUser.getNickName()),
                    InvoiceNodeEnum.NODE_2.getDesc(),
                    sysUser,
                    true,
                    true
            );
        }

        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void withdraw(InvoiceApplyDetailPO param) {
        // 1.更改状态
        LambdaUpdateWrapper<AdsMatHyxtInvoiceApplyD> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(AdsMatHyxtInvoiceApplyD::getId, param.getId());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getStatus, 0);
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentNode, InvoiceNodeEnum.NODE_0.getNode());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getNodeLabel, InvoiceNodeEnum.NODE_0.getDesc());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentAuditUser, "");
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentAuditUserName, "");
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentAuditUserPhone, "");
        this.update(updateWrapper);

        // 2.删除待办任务
        adsMatHyxtTaskRunDService.delete(param.getId());

        // 3.删除已办任务
        adsMatHyxtTaskHistoryDService.delete(param.getId());
    }

    @Override
    public void updateAuditUser(String id, String au1, String au2, String au3, String au4, String au5, String au6) {
        LambdaUpdateWrapper<AdsMatHyxtInvoiceApplyD> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(AdsMatHyxtInvoiceApplyD::getId, id);
        if (null != au1) {
            updateWrapper.set(AdsMatHyxtInvoiceApplyD::getAuditUser1, au1);
        }
        if (null != au2) {
            updateWrapper.set(AdsMatHyxtInvoiceApplyD::getAuditUser2, au2);
        }
        if (null != au3) {
            updateWrapper.set(AdsMatHyxtInvoiceApplyD::getAuditUser3, au3);
        }
        if (null != au4) {
            updateWrapper.set(AdsMatHyxtInvoiceApplyD::getAuditUser4, au4);
        }
        if (null != au5) {
            updateWrapper.set(AdsMatHyxtInvoiceApplyD::getAuditUser5, au5);
        }
        if (null != au6) {
            updateWrapper.set(AdsMatHyxtInvoiceApplyD::getAuditUser6, au6);
        }
        this.update(updateWrapper);
    }

    @Override
    public void updateNode(String id, InvoiceNodeEnum node, String currentAuditUser, String currentAuditUserName, String currentAuditUserPhone) {
        LambdaUpdateWrapper<AdsMatHyxtInvoiceApplyD> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(AdsMatHyxtInvoiceApplyD::getId, id);
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getStatus, node.getStatus());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentNode, node.getNode());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getNodeLabel, node.getDesc());
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentAuditUser, currentAuditUser);
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentAuditUserName, currentAuditUserName);
        updateWrapper.set(AdsMatHyxtInvoiceApplyD::getCurrentAuditUserPhone, currentAuditUserPhone);
        this.update(updateWrapper);
    }
}
