package com.usky.oa.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.core.exception.BusinessException;
import com.usky.common.security.utils.SecurityUtils;
import com.usky.oa.domain.*;
import com.usky.oa.mapper.*;
import com.usky.oa.service.OaApprovalService;
import com.usky.common.mybatis.core.AbstractCrudService;
// import com.usky.oa.service.utils.OaProcessAnalysis;
import com.usky.oa.service.utils.OaSendMessageCenter;
import com.usky.oa.service.vo.OaApprovalCountVO;
import com.usky.system.domain.SysUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 审批表 服务实现类
 * </p>
 *
 * @author fu
 * @since 2024-12-10
 */
@Service
public class OaApprovalServiceImpl extends AbstractCrudService<OaApprovalMapper, OaApproval> implements OaApprovalService {

    @Autowired
    private OaApprovalMapper oaApprovalMapper;

    @Autowired
    private OaDocumentMapper oaDocumentMapper;

    @Autowired
    private OaSendMessageCenter oaSendMessageCenter;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private OaNodeMapper oaNodeMapper;

    @Autowired
    private SysUserPostMapper sysUserPostMapper;

/*    @Autowired
    private OaProcessAnalysis oaProcessAnalysis;*/

    @Autowired
    private OaFormDefinitionMapper oaFormDefinitionMapper;


    // 我的申请-待处理、已处理、我发起、我收到-统计(暂时统计近一年数据)
    @Override
    public OaApprovalCountVO approvalCount() {
        Long userId = SecurityUtils.getUserId();
        String username = SecurityUtils.getUsername();
        Integer tenantId = SecurityUtils.getTenantId();

        LocalDateTime now = LocalDateTime.now();
        // 一年前时间
        LocalDateTime oneYearAgo = now.minusYears(1);

        OaApprovalCountVO oaApprovalCountVO = new OaApprovalCountVO();
        // 待处理
        oaApprovalCountVO.setPendingSum(getPendingSum(tenantId, userId, oneYearAgo, now).size());
        // 已处理
        oaApprovalCountVO.setAlreadySum(getAlreadySum(tenantId, userId, oneYearAgo, now).size());
        // 我发起
        oaApprovalCountVO.setMyInitiated(getMyInitiated(tenantId, username, oneYearAgo, now).size());
        // 我收到
        oaApprovalCountVO.setMyReceived(getMyReceived(tenantId, userId, oneYearAgo, now).size());

        return oaApprovalCountVO;
    }

    // 我的代办-待处理、已处理、我收到-分页
    @Override
    public CommonPage<OaApproval> pageList(Integer queryType, String docNo, String formSign, Integer approvalStatus, String startTime, String endTime, Integer pageNum, Integer pageSize) {
        Long userId = SecurityUtils.getUserId();
        Integer tenantId = SecurityUtils.getTenantId();
        IPage<OaApproval> page = new Page<>(pageNum, pageSize);

        List<Integer> processed = Stream.of(2, 3).collect(Collectors.toList());

        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(OaApproval::getTenantId, tenantId)
                .eq(OaApproval::getApprovalUid, userId)
                .orderByDesc(OaApproval::getId);

        switch (queryType) {
            case 1:
                queryWrapper.eq(OaApproval::getApprovalStatus, 1)
                        .like(StringUtils.isNotBlank(docNo), OaApproval::getDocNo, docNo)
                        .like(StringUtils.isNotBlank(formSign), OaApproval::getDocNo, formSign)
                        .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), OaApproval::getSubmitDate, startTime, endTime)
                        .orderByDesc(OaApproval::getSubmitDate);
                break;
            case 2:
                queryWrapper.like(StringUtils.isNotBlank(docNo), OaApproval::getDocNo, docNo)
                        .like(StringUtils.isNotBlank(formSign), OaApproval::getDocNo, formSign)
                        .eq(approvalStatus != null && approvalStatus > 1 && approvalStatus < 4, OaApproval::getApprovalStatus, approvalStatus)
                        .in(OaApproval::getApprovalStatus, processed)
                        .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), OaApproval::getSubmitDate, startTime, endTime)
                        .orderByDesc(OaApproval::getApprovalDate);
                break;
            case 3:
                queryWrapper.like(StringUtils.isNotBlank(docNo), OaApproval::getDocNo, docNo)
                        .like(StringUtils.isNotBlank(formSign), OaApproval::getDocNo, formSign)
                        .eq(OaApproval::getType, 2)
                        .eq(approvalStatus != null && approvalStatus > 0 && approvalStatus < 4, OaApproval::getApprovalStatus, approvalStatus)
                        .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), OaApproval::getSubmitDate, startTime, endTime)
                        .orderByDesc(OaApproval::getSubmitDate);
                break;
            case 4:

            default:
                throw new RuntimeException("查询类型参数错误");
        }

        IPage<OaApproval> resultPage = oaApprovalMapper.selectPage(page, queryWrapper);

        // 获取真实姓名
        List<Long> userIds = resultPage.getRecords().stream()
                .map(oaApproval -> ((long) oaApproval.getProposer()))
                .distinct()
                .collect(Collectors.toList());
        if (!userIds.isEmpty()) {
            LambdaQueryWrapper<SysUser> userQueryWrapper = Wrappers.lambdaQuery();
            userQueryWrapper.in(SysUser::getUserId, userIds).select(SysUser::getUserId, SysUser::getNickName);
            Map<Long, String> userNicknameMap = sysUserMapper.selectList(userQueryWrapper).stream()
                    .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName));
            for (OaApproval oaApproval : resultPage.getRecords()) {
                oaApproval.setCreateBy(userNicknameMap.get(oaApproval.getProposer().longValue()));
            }
        }

        return ToCommonPage(resultPage);
    }

    // 审批
    @Transactional
    @Override
    public void approve(Integer id, Integer approvalStatus, String opinion) {
        Long userId = SecurityUtils.getUserId();
        String username = SecurityUtils.getUsername();
        LocalDateTime now = LocalDateTime.now();
        Integer tenantId = SecurityUtils.getTenantId();

        LambdaQueryWrapper<SysUser> userQuery = new LambdaQueryWrapper<>();
        userQuery.select(SysUser::getUserId, SysUser::getDeptId)
                .eq(SysUser::getTenantId, tenantId)
                .eq(SysUser::getDelFlag, 0)
                .eq(SysUser::getStatus, 0);
        Map<Long, Long> userDeptMap = sysUserMapper.selectList(userQuery).stream()
                .collect(Collectors.toMap(SysUser::getUserId, SysUser::getDeptId));

        OaApproval oaApproval = oaApprovalMapper.selectOne(Wrappers.<OaApproval>lambdaQuery().eq(OaApproval::getId, id));

        if (oaApproval == null) {
            throw new BusinessException("审批信息不存在！请联系管理员");
        }
        if (!oaApproval.getApprovalUid().equals(SecurityUtils.getUserId())) {
            throw new BusinessException("审批权限不足，暂时无法更改！");
        }
        if (oaApproval.getApprovalStatus() != 1) {
            throw new BusinessException("审批状态异常，暂时无法更改！");
        }
        if (approvalStatus < 2 || approvalStatus > 3) {
            throw new BusinessException("审批类型错误，请重试！");
        }

        oaApproval.setApprovalUid(userId);
        oaApproval.setApprovalStatus(approvalStatus);
        oaApproval.setOpinion(opinion == null ? "" : opinion);
        oaApproval.setApprovalDate(now);
        oaApproval.setUpdateBy(username);
        oaApproval.setUpdateTime(now);
        oaApprovalMapper.updateById(oaApproval);

        if (approvalStatus == 2) {
            Integer nodeId = oaApprovalMapper.selectById(oaApproval.getId()).getNodeId();
            List<OaNode> oaNodes = oaNodeMapper.selectList(Wrappers.<OaNode>lambdaQuery().eq(OaNode::getParentId, nodeId));
            if (!oaNodes.isEmpty()) {
                for (OaNode oaNode : oaNodes) {
                    List<Long> userIds = new ArrayList<>();
                    switch (oaNode.getNodeScope()) {
                        case 0:
                        case 1:
                        case 2:
                            userIds = Arrays.stream(oaNode.getProposer().split(",")).map(Long::parseLong).collect(Collectors.toList());
                            break;
                        case 3:
                            LambdaQueryWrapper<SysUser> userQuery1 = new LambdaQueryWrapper<>();
                            userQuery1.select(SysUser::getUserId, SysUser::getNickName, SysUser::getDeptId)
                                    .eq(SysUser::getTenantId, tenantId)
                                    .eq(SysUser::getDelFlag, 0)
                                    .eq(SysUser::getStatus, 0)
                                    .eq(SysUser::getDeptId, oaNode.getDeptId());
                            userIds = sysUserMapper.selectList(userQuery1).stream().map(SysUser::getUserId).collect(Collectors.toList());
                            break;
                        case 4:
                            LambdaQueryWrapper<SysUserPost> userRoleQuery = new LambdaQueryWrapper<>();
                            userRoleQuery.eq(SysUserPost::getPostId, oaNode.getJobId());
                            userIds = sysUserPostMapper.selectList(userRoleQuery).stream().map(SysUserPost::getUserId).collect(Collectors.toList());
                            break;
                    }

                    if (userIds.isEmpty()) {
                        log.error("审批节点无用户，审批失败！");
                    } else {
                        for (Long userId1 : userIds) {
                            OaApproval approval = new OaApproval();
                            approval.setDocNo(oaApproval.getDocNo());
                            approval.setProposer(oaApproval.getProposer());
                            approval.setApprovalUid(userId1);
                            approval.setType(oaNode.getNodeType());
                            approval.setApprovalStatus(1);
                            approval.setSubmitDate(now);
                            approval.setCreateTime(now);
                            approval.setCreateBy(username);
                            approval.setDeptId(userDeptMap.get(userId1));
                            approval.setTenantId(tenantId);
                            approval.setNodeId(oaNode.getId());
                            oaApprovalMapper.insert(approval);

                            // 发送消息通知下一步审批人
                            oaSendMessageCenter.sendAsyncMessage(
                                    tenantId,
                                    oaApproval.getCreateBy(),
                                    oaApproval.getApprovalUid(),
                                    approval.getId(),
                                    userIds,
                                    3,
                                    getFieldInfo(oaApproval.getDocNo())
                            );
                        }
                    }
                }
            }
            // 后无节点，发送消息通知申请人审核通过
            else {
                Long proposerId = Long.valueOf(oaApproval.getProposer());
                oaSendMessageCenter.sendAsyncMessage(
                        tenantId,
                        oaApproval.getCreateBy(),
                        oaApproval.getApprovalUid(),
                        oaApproval.getId(),
                        Collections.singletonList(proposerId),
                        1,
                        getFieldInfo(oaApproval.getDocNo())
                );
            }
        } else if (oaApproval.getApprovalStatus() == 3) {
            Long proposerId = Long.valueOf(oaApproval.getProposer());
            // 发送消息通知申请人审核不通过
            oaSendMessageCenter.sendAsyncMessage(
                    tenantId,
                    oaApproval.getCreateBy(),
                    oaApproval.getApprovalUid(),
                    oaApproval.getId(),
                    Collections.singletonList(proposerId),
                    0,
                    getFieldInfo(oaApproval.getDocNo())
            );
        }
    }

    @Override
    public String getFieldInfo(String docNo) {
        String sgin = docNo.split("-")[0];
        LambdaQueryWrapper<OaFormDefinition> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(OaFormDefinition::getFieldInfo)
                .eq(OaFormDefinition::getFormSign, sgin);
        OaFormDefinition oaFormDefinition = oaFormDefinitionMapper.selectOne(queryWrapper);
        return oaFormDefinition.getFieldInfo();
    }

    // xml 流程解析测试
/*    @Override
    public void analysisTest(Integer id) {
        LambdaQueryWrapper<OaFormDefinition> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(OaFormDefinition::getId, id);
        String flowInfo = oaFormDefinitionMapper.selectOne(queryWrapper).getFlowInfo();
        oaProcessAnalysis.processAnalysis(flowInfo);
    }*/

    // 待处理
    private List<OaApproval> getPendingSum(Integer tenantId, Long userId, LocalDateTime oneYearAgo, LocalDateTime now) {
        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(OaApproval::getTenantId, tenantId)
                .eq(OaApproval::getApprovalUid, userId)
                .eq(OaApproval::getApprovalStatus, 1)
                .between(OaApproval::getSubmitDate, oneYearAgo, now);
        List<OaApproval> oaApprovals = oaApprovalMapper.selectList(queryWrapper);
        return oaApprovals == null ? Collections.emptyList() : oaApprovals;
    }

    // 已处理
    private List<OaApproval> getAlreadySum(Integer tenantId, Long userId, LocalDateTime oneYearAgo, LocalDateTime now) {
        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(OaApproval::getTenantId, tenantId)
                .eq(OaApproval::getApprovalUid, userId)
                .and(wrapper -> wrapper
                        .eq(OaApproval::getApprovalStatus, 2)
                        .or()
                        .eq(OaApproval::getApprovalStatus, 3))
                .between(OaApproval::getSubmitDate, oneYearAgo, now);
        List<OaApproval> oaApprovals = oaApprovalMapper.selectList(queryWrapper);
        return oaApprovals == null ? Collections.emptyList() : oaApprovals;
    }

    // 我发起
    /*private List<OaApproval> getMyInitiated(Integer tenantId, String username) {
        List<String> docNoList = oaDocumentMapper.selectList(new QueryWrapper<OaDocument>().lambda()
                .select(OaDocument::getDocNo)
                .eq(OaDocument::getTenantId, tenantId)
                .eq(OaDocument::getCreateBy, username)
                // 已发起只计算 审批中、审通过、审批不通过
                .in(OaDocument::getDocStatus, 1, 2, 3)).stream().map(OaDocument::getDocNo).collect(Collectors.toList());

        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(OaApproval::getDocNo, docNoList);
        List<OaApproval> oaApprovals = oaApprovalMapper.selectList(queryWrapper);
        return oaApprovals == null ? Collections.emptyList() : oaApprovals;
    }*/

    // 我发起
    private List<OaDocument> getMyInitiated(Integer tenantId, String username, LocalDateTime oneYearAgo, LocalDateTime now) {
        List<OaDocument> oaDocuments = oaDocumentMapper.selectList(new QueryWrapper<OaDocument>().lambda()
                .select(OaDocument::getDocNo)
                .eq(OaDocument::getTenantId, tenantId)
                .eq(OaDocument::getCreateBy, username)
                .in(OaDocument::getDocStatus, 1, 2, 3)
                .between(OaDocument::getCreateTime, oneYearAgo, now));
        return oaDocuments == null ? Collections.emptyList() : oaDocuments;
    }

    // 我收到
    private List<OaApproval> getMyReceived(Integer tenantId, Long userId, LocalDateTime oneYearAgo, LocalDateTime now) {
        LambdaQueryWrapper<OaApproval> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(OaApproval::getTenantId, tenantId)
                .eq(OaApproval::getApprovalUid, userId)
                .eq(OaApproval::getType, 2)
                .between(OaApproval::getSubmitDate, oneYearAgo, now);
        List<OaApproval> oaApprovals = oaApprovalMapper.selectList(queryWrapper);
        return oaApprovals == null ? Collections.emptyList() : oaApprovals;
    }

}
