package com.ruoyi.interfaces.service.impl;

import com.github.pagehelper.PageHelper;
import com.ruoyi.common.exception.CheckException;
import com.ruoyi.common.utils.CheckUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.interfaces.core.page.Page;
import com.ruoyi.interfaces.core.page.PageParam;
import com.ruoyi.interfaces.core.page.PageUtils;
import com.ruoyi.interfaces.domain.*;
import com.ruoyi.interfaces.domain.vo.PtServiceApplyVo;
import com.ruoyi.interfaces.mapper.PtServiceApplyDao;
import com.ruoyi.interfaces.mapper.PtServiceAuthMapper;
import com.ruoyi.interfaces.service.PtAppService;
import com.ruoyi.interfaces.service.PtFileService;
import com.ruoyi.interfaces.service.PtServiceApplyService;
import com.ruoyi.interfaces.service.PtServiceService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author weking
 * @date 2019-4-25
 */
@Service
@Transactional
public class PtServiceApplyServiceImpl implements PtServiceApplyService {

    private final PtServiceApplyDao ptServiceApplyDao;

    @Autowired
    private PtServiceAuthMapper ptServiceAuthMapper;

    @Autowired
    private PtServiceService ptSrvService;

    @Autowired
    private PtAppService ptAppService;

    @Autowired
    private PtFileService ptFileService;

    public PtServiceApplyServiceImpl(PtServiceApplyDao ptServiceApplyDao) {
        this.ptServiceApplyDao = ptServiceApplyDao;
    }

    @Override
    public int insert(PtServiceApply ptServiceApply) {
        ptServiceApply.setId(IdUtils.simpleUUID());
        ptServiceApply.setApplyState("0");
        ptServiceApply.setApproveTime(new Date());
        // 更新申请数量
        updateApplyNum(ptServiceApply.getSrvId());
        // 关联附件
        updateFile(ptServiceApply);
        return ptServiceApplyDao.insert(ptServiceApply);
    }

    /**
     * 关联申请附件
     *
     * @param ptServiceApply
     */
    private void updateFile(PtServiceApply ptServiceApply) {
        String id = ptServiceApply.getId();
        Optional.of(ptServiceApply).map(PtServiceApply::getFileList).ifPresent(list -> {
            list.forEach(ptFile -> {
                ptFile.setRelId(id);
                ptFileService.update(ptFile);
            });
        });
    }

    /**
     * 更新申请数量
     *
     * @param srvId 服务ID
     */
    private void updateApplyNum(String srvId) {
        PtService service = ptSrvService.get(srvId);
        Optional.ofNullable(service).ifPresent(s -> {
            PtService ptService = new PtService();
            ptService.setSrvId(s.getSrvId());
            ptService.setApplyNum(s.getApplyNum() + 1);
            ptSrvService.update(ptService);
        });

    }

    @Override
    public Page listOfPage(PageParam<PtServiceApply> pageParam) {
        PtServiceApply serviceApply = Optional.ofNullable(pageParam.getData()).orElse(new PtServiceApply());
        serviceApply.setApproveUser(String.valueOf(SecurityUtils.getUserId()));
        serviceApply.setApplyState("1");
        PageHelper.startPage(pageParam);
        List<PtServiceApply> list = ptServiceApplyDao.selectByPrimaryKey(serviceApply);
        return PageUtils.convert(convertPtServiceApply(list));
    }

    /**
     * 转换 PtServiceApply 为 PtServiceApplyVo
     *
     * @param applyList 申请列表
     * @return 申请列表
     */
    @Override
    public List<PtServiceApplyVo> convertPtServiceApply(List<PtServiceApply> applyList) {
        List<PtServiceApplyVo> list = new ArrayList<>();
        if (CollectionUtils.isEmpty(applyList)) {
            return list;
        }
        applyList.forEach(apply -> {
            PtServiceApplyVo vo = new PtServiceApplyVo();
            BeanUtils.copyProperties(apply, vo);
            Optional.of(apply).map(PtServiceApply::getAppId).ifPresent(appId -> {
                vo.setAppIdArray(appId.split(","));
                List<PtApp> appList = ptAppService.listByIds(vo.getAppIdArray());
                if (CollectionUtils.isNotEmpty(appList)) {
                    vo.setAppName(
                            appList.stream()
                                    .filter(Objects::nonNull)
                                    .map(PtApp::getAppName)
                                    .toArray(String[]::new)
                    );
                }
            });
            list.add(vo);
        });
        return list;
    }

    @Override
    public List<PtServiceApply> list(PtServiceApply ptServiceApply) {
        return ptServiceApplyDao.selectByPrimaryKey(ptServiceApply);
    }

    @Override
    public int updateByPrimaryKey(PtServiceApply ptServiceApply) {
        CheckUtils.notEmpty(ptServiceApply.getId(), "id.no");
        int ret = ptServiceApplyDao.updateByPrimaryKey(ptServiceApply);
        if ("1".equals(ptServiceApply.getApplyState())) {
            addServiceAuth(ptServiceApply);
        }
        return ret;
    }

    private void addServiceAuth(PtServiceApply ptServiceApply) {
        ptServiceAuthMapper.insert(PtServiceAuth.builder()
                .id(IdUtils.simpleUUID())
                .srvId(ptServiceApply.getSrvId())
                .userId(ptServiceApply.getUserName())
                .appId(ptServiceApply.getAppId())
                .deadline(ptServiceApply.getApplyExpire())
                .build());
    }

    @Override
    public int deleteByPrimaryKey(String id) {
        return ptServiceApplyDao.deleteByPrimaryKey(id);
    }

    @Override
    public PtServiceApplyVo get(String id) {
        PtServiceApply apply = ptServiceApplyDao.get(id);
        Optional.ofNullable(apply).orElseThrow(() -> new CheckException("id invalid"));

        PtServiceApplyVo vo = new PtServiceApplyVo();
        BeanUtils.copyProperties(apply, vo);
        Optional.of(apply).map(PtServiceApply::getAppId).ifPresent(appId -> {
            vo.setAppIdArray(appId.split(","));
            List<PtApp> appList = ptAppService.listByIds(vo.getAppIdArray());
            if (CollectionUtils.isNotEmpty(appList)) {
                vo.setAppName(
                        appList.stream()
                                .filter(Objects::nonNull)
                                .map(PtApp::getAppName)
                                .toArray(String[]::new)
                );
            }
        });
        List<PtFile> fileList = ptFileService.listByRelId(vo.getId());
        vo.setFileList(Optional.ofNullable(fileList).orElse(new ArrayList<>(0)));
        return vo;
    }

    @Override
    public boolean checkAuth(String appId, String srvId) {
        if (StringUtils.isBlank(appId) && StringUtils.isBlank(srvId)) {
            return false;
        }
        PtServiceApply apply = new PtServiceApply();
        apply.setAppId(appId);
        apply.setSrvId(srvId);
        PtServiceApply ptServiceApply = ptServiceApplyDao.getByAuth(apply);
        return ptServiceApply != null;
    }

}
