package com.usky.oa.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
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.oa.service.OaFbdDocumentService;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.oa.service.utils.OaApprovalGeneration;
import com.usky.oa.service.utils.OaSendMessageCenter;
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 java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 发布申请表 服务实现类
 * </p>
 *
 * @author fu
 * @since 2025-02-20
 */
@Service
public class OaFbdDocumentServiceImpl extends AbstractCrudService<OaFbdDocumentMapper, OaFbdDocument> implements OaFbdDocumentService {

    @Autowired
    private OaFormDefinitionMapper oaFormDefinitionMapper;

    @Autowired
    private OaDocumentMapper oaDocumentMapper;

    @Autowired
    private OaFbdDocumentMapper oaFbdDocumentMapper;

    @Autowired
    private OaApprovalMapper oaApprovalMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysUserPostMapper sysUserPostMapper;

    @Autowired
    private OaApprovalGeneration oaApprovalGeneration;

    @Autowired
    private OaSendMessageCenter oaSendMessageCenter;

    @Autowired
    private OaApprovalService oaApprovalService;

    @Override
    public void addOrUpDate(OaFbdDocument oaFbdDocument, JSONObject node) {
        // 校验表单数据
        validateDocument(oaFbdDocument);

        String username = SecurityUtils.getUsername();
        LocalDateTime now = LocalDateTime.now();
        Integer tenantId = SecurityUtils.getTenantId();
        String sign = null;

        if (oaFbdDocument.getId() == null) {
            // 插入操作
            Long userId = SecurityUtils.getUserId();
            Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHHmmss");
            String formattedDate = now.format(formatter);

            LambdaQueryWrapper<OaFormDefinition> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.select(OaFormDefinition::getFormSign).eq(OaFormDefinition::getId, oaFbdDocument.getFormId());
            OaFormDefinition oaFormDefinition = oaFormDefinitionMapper.selectOne(queryWrapper);
            sign = oaFormDefinition.getFormSign();
            String docNo = sign + "-" + formattedDate;

            oaFbdDocument.setDocNo(docNo);
            oaFbdDocument.setProposer(userId);
            oaFbdDocument.setCreateBy(username);
            oaFbdDocument.setCreateTime(now);
            oaFbdDocument.setDeptId(deptId);
            oaFbdDocument.setTenantId(tenantId);
            oaFbdDocumentMapper.insert(oaFbdDocument);

            // 插入单据表数据
            OaDocument oaDocument = new OaDocument();
            oaDocument.setFormId(oaFbdDocument.getFormId());
            oaDocument.setType(sign);
            oaDocument.setDocNo(docNo);
            oaDocument.setProposer(userId);
            oaDocument.setDocStatus(oaFbdDocument.getDocStatus());
            oaDocument.setCreateBy(username);
            oaDocument.setCreateTime(now);
            oaDocument.setDeptId(deptId);
            oaDocument.setTenantId(tenantId);
            oaDocumentMapper.insert(oaDocument);

            if (oaFbdDocument.getDocStatus().equals(1)) {
                getOaApproval(oaFbdDocument);
            }
        } else {
            // 更新操作
            oaFbdDocument.setUpdateBy(username);
            oaFbdDocument.setUpdateTime(now);
            oaFbdDocumentMapper.updateById(oaFbdDocument);

            oaDocumentMapper.update(null, Wrappers.lambdaUpdate(OaDocument.class)
                    .eq(OaDocument::getDocNo, oaFbdDocument.getDocNo())
                    .set(OaDocument::getDocStatus, oaFbdDocument.getDocStatus())
                    .set(OaDocument::getUpdateBy, username)
                    .set(OaDocument::getUpdateTime, now)
            );

            if (oaFbdDocument.getDocStatus() == 1) {
                OaFbdDocument updatedDocument = oaFbdDocumentMapper.selectById(oaFbdDocument.getId());
                getOaApproval(updatedDocument);
            }

            sign = oaFbdDocumentMapper.selectById(oaFbdDocument.getId()).getDocNo().split("-")[0];
        }
        oaApprovalGeneration.nodeSave(node, sign);
    }

    // 获取审批表数据
    @Override
    public void getOaApproval(OaFbdDocument oaFbdDocument) {
        String docNo = oaFbdDocument.getDocNo();
        String formSign = docNo.split("-")[0];
        OaFlow oaFlow = oaApprovalGeneration.selectBySign(formSign);
        OaNode oaNode = oaApprovalGeneration.selectByFlowId(oaFlow.getId());

        List<Long> userIds = new ArrayList<>();

        switch (oaNode.getNodeScope()) {
            case 0:
                userIds = Arrays.stream(oaNode.getProposer().split(",")).map(Long::parseLong).collect(Collectors.toList());
                break;
            case 3:
                LambdaQueryWrapper<SysUser> userQuery = new LambdaQueryWrapper<>();
                userQuery.select(SysUser::getUserId)
                        .eq(SysUser::getTenantId, oaFlow.getTenantId())
                        .eq(SysUser::getDelFlag, 0)
                        .eq(SysUser::getStatus, 0)
                        .eq(SysUser::getDeptId, oaNode.getDeptId());
                userIds = sysUserMapper.selectList(userQuery).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;
        }

        for (Long userId1 : userIds) {
            OaApproval approval = new OaApproval();
            approval.setDocNo(docNo);
            approval.setProposer(Math.toIntExact(oaFbdDocument.getProposer()));
            approval.setType(oaNode.getNodeType());
            approval.setApprovalStatus(1);
            approval.setApprovalUid(userId1);
            approval.setSubmitDate(oaFbdDocument.getCreateTime());
            approval.setCreateTime(oaFbdDocument.getCreateTime());
            approval.setCreateBy(oaFbdDocument.getCreateBy());
            approval.setDeptId(oaFbdDocument.getDeptId());
            approval.setTenantId(oaFbdDocument.getTenantId());
            approval.setNodeId(oaNode.getId());
            oaApprovalMapper.insert(approval);

            oaSendMessageCenter.sendAsyncMessage(
                    oaFbdDocument.getTenantId(),
                    oaFbdDocument.getCreateBy(),
                    approval.getApprovalUid(),
                    oaFbdDocument.getId(),
                    userIds,
                    3,
                    oaApprovalService.getFieldInfo(oaFbdDocument.getDocNo())
            );
        }

    }

    /**
     * 校验表单数据
     * @param oaFbdDocument
     */
    private void validateDocument(OaFbdDocument oaFbdDocument) {
        if (StringUtils.isBlank(oaFbdDocument.getApplicationName())) {
            throw new BusinessException("申请名称不能为空！");
        } else if (oaFbdDocument.getApplicationName().length() > 16) {
            throw new BusinessException("申请名称长度不能超过16个字符!");
        } else if (oaFbdDocument.getPublishTime() == null) {
            throw new BusinessException("发布时间不能为空！");
        } else if (oaFbdDocument.getPublishTime().isBefore(LocalDateTime.now())) {
            throw new BusinessException("发布时间不能早于当前时间！");
        } else if (oaFbdDocument.getApplicationName().length() > 15) {
            throw new BusinessException("申请名称长度不能超过15个字符!");
        } else if (StringUtils.isBlank(oaFbdDocument.getPublishProject())) {
            throw new BusinessException("发布项目不能为空！");
        } else if (oaFbdDocument.getPublishProject().length() > 64) {
            throw new BusinessException("发布项目名称长度不能超过64个字符!");
        } else if (oaFbdDocument.getProjectType() == null) {
            throw new BusinessException("项目类型不能为空!");
        } else if (oaFbdDocument.getProjectType() < 1 || oaFbdDocument.getProjectType() > 2) {
            throw new BusinessException("项目类型传参有误!");
        } else if (StringUtils.isBlank(oaFbdDocument.getOnlineFunction())) {
            throw new BusinessException("上线功能不能为空!");
        } else if (oaFbdDocument.getOnlineFunction().length() > 250) {
            throw new BusinessException("上线功能长度不能超过250个字!");
        } else if (oaFbdDocument.getPreparation() != null && oaFbdDocument.getPreparation().length() > 64) {
            throw new BusinessException("上线前准备不能超过250个字!");
        } else if (oaFbdDocument.getAnnex() != null && oaFbdDocument.getAnnex().length() > 500) {
            throw new BusinessException("附件上传数量超!");
        }
    }


}
