package com.hzs.system.base.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.constant.SystemFieldConstants;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.CommonUtil;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.domain.system.base.BdNotice;
import com.hzs.common.domain.system.base.BdNoticeDetail;
import com.hzs.common.domain.system.config.BdAwards;
import com.hzs.common.domain.system.config.BdGrade;
import com.hzs.common.domain.system.ext.BdNoticeExt;
import com.hzs.common.domain.system.sys.SysRole;
import com.hzs.system.base.mapper.BdNoticeMapper;
import com.hzs.system.base.service.IBdNoticeDetailService;
import com.hzs.system.base.service.IBdNoticeService;
import com.hzs.system.base.vo.*;
import com.hzs.system.config.service.IBdAwardsService;
import com.hzs.system.config.service.IBdGradeService;
import com.hzs.system.config.service.IBdNoticeConfigService;
import com.hzs.system.sys.IApprovalServiceApi;
import com.hzs.system.sys.dto.ApprovalSubmitDTO;
import com.hzs.system.sys.service.ISysRoleService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 公告表 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2022-08-09
 */
@Service
public class BdNoticeServiceImpl extends ServiceImpl<BdNoticeMapper, BdNotice> implements IBdNoticeService {


    @Autowired
    private IBdNoticeConfigService noticeConfigService;

    @Autowired
    private ISysRoleService sysRoleService;

    @Autowired
    private IBdGradeService gradeService;

    @Autowired
    private IBdAwardsService awardsService;

    @Autowired
    private IBdNoticeDetailService iBdNoticeDetailService;

    @DubboReference
    IApprovalServiceApi approvalServiceApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveNotice(NoticePetitionVO noticePetitionVO) {
        BdNoticeVO noticeVO = noticePetitionVO.getNotice();
        Long pkMember = noticeVO.getPkMember();
        BdNotice notice = BeanUtil.copyProperties(noticeVO, BdNotice.class);
        notice.setPkCreator(pkMember);
        notice.setApproveState(EApproveRechargeStatus.WAIT.getValue());
        String module = noticeVO.getFunctionType().equals(ENoticeFunctionType.NOTICE.getValue()) ? EOrderPrefix.NOTICE.getValue() : EOrderPrefix.MESSAGE_PLATFORM.getValue();
        String batchCode = CommonUtil.createSerialNumber(module);
        notice.setApprover(pkMember);
        notice.setModifiedTime(new Date());
        notice.setBatch(batchCode);
        //前台公告获取最大排序值
        if (noticeVO.getFunctionType().equals(ENoticeFunctionType.NOTICE.getValue())
                && noticeVO.getWebsiteType().equals(ENoticeWebsiteType.MEMBER.getValue())) {
            notice.setSort(baseMapper.selectMaxSort(noticeVO.getPkCountry()));
        }

        Boolean result = save(notice);
        submitApproval(noticePetitionVO, batchCode);
        return result;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean adminSaveNotice(NoticePetitionVO noticePetitionVO) {
        BdNoticeVO noticeVO = noticePetitionVO.getNotice();
        Long pkMember = noticeVO.getPkMember();
        BdNotice notice = BeanUtil.copyProperties(noticeVO, BdNotice.class);
        notice.setPkCreator(pkMember);
        notice.setApprover(pkMember);
        notice.setModifiedTime(new Date());
        notice.setApproveState(EApproveRechargeStatus.WAIT.getValue());
        String module = noticeVO.getFunctionType().equals(ENoticeFunctionType.NOTICE.getValue()) ? EOrderPrefix.NOTICE.getValue() : EOrderPrefix.MESSAGE_PLATFORM.getValue();
        String batchCode = CommonUtil.createSerialNumber(module);
        notice.setBatch(batchCode);
        Boolean result = save(notice);
        submitApproval(noticePetitionVO, batchCode);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteNoticePetition(NoticePetitionVO noticePetitionVO) {
        String module = EOrderPrefix.NOTICE.getValue();
        String batchCode = CommonUtil.createSerialNumber(module);
        BdNoticeVO noticeVO = noticePetitionVO.getNotice();
        noticeVO.setOperateType(EControlType.DELETE.getValue());
        return submitApproval(noticePetitionVO, batchCode);
    }


    /**
     * 提交审批
     *
     * @param noticePetitionVO 公告信息
     */
    private Boolean submitApproval(NoticePetitionVO noticePetitionVO, String batchCode) {
        BdNoticeVO noticeVO = noticePetitionVO.getNotice();
        EApprovalBusiness approvalBusiness = getEApprovalBusiness(noticeVO);
        JSONConfig jsonConfig = JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss");
        ApprovalSubmitDTO approvalSubmitDTO = ApprovalSubmitDTO.builder().eApprovalBusiness(approvalBusiness)
                .businessCode(batchCode).businessData(JSONUtil.toJsonStr(Collections.singletonList(noticeVO), jsonConfig))
                .signType(ESignType.getEnumByValue(noticePetitionVO.getSignType())).userIdList(noticePetitionVO.getUserIdList())
                .sendIdList(noticePetitionVO.getSendIdList())
                .remark(noticePetitionVO.getRemark()).build();
        R<String> submit = approvalServiceApi.submit(approvalSubmitDTO, noticeVO.getLoginUser());
        if (!submit.isSuccess()) {
            throw new RuntimeException("公告、站内信提交审批失败！");
        } else {
            return true;
        }
    }

    /**
     * 获取业务审批类型
     *
     * @param noticeVO 公告信息
     * @return EApprovalBusiness
     */
    private EApprovalBusiness getEApprovalBusiness(BdNoticeVO noticeVO) {
        Integer functionType = noticeVO.getFunctionType();
        Integer websiteType = noticeVO.getWebsiteType();
        if (websiteType.equals(ENoticeWebsiteType.MEMBER.getValue())) {
            return EApprovalBusiness.MEMBER_NOTICE;
        } else {
            return EApprovalBusiness.ADMIN_NOTICE;
        }
    }

    @Override
    public Object[] getMemberNotice(BdNoticeVO noticeVO) {
        BdNoticeVO bdNoticeVO;
        List<BdNoticeVO> bdNoticeVOList = new ArrayList<>();
        List<BdNotice> noticeList = baseMapper.getMemberNotice(noticeVO);
        if (CollUtil.isNotEmpty(noticeList)) {
            for (BdNotice notice : noticeList) {
                bdNoticeVO = changeTranslate(notice);
                bdNoticeVOList.add(bdNoticeVO);
            }
        }
        return new Object[]{noticeList, bdNoticeVOList};
    }

    /**
     * 前台转化翻译
     *
     * @param notice 公告
     * @return BdNoticeVO
     */
    private BdNoticeVO changeTranslate(BdNotice notice) {
        BdNoticeVO bdNoticeVO = BeanUtil.copyProperties(notice, BdNoticeVO.class);
        //等级翻译
        bdNoticeVO.setNoticeGradeVOList(getGradeTranslate(notice.getGrade()));
        //奖衔翻译
        bdNoticeVO.setAwardsVOList(getAwardTranslate(notice.getAwards()));
        //发布位置翻译
        bdNoticeVO.setLocationVOList(getLocationTranslate(notice.getPublishLocation()));
        //角色
        bdNoticeVO.setRoleNames(getRoleNamesTranslate(notice.getRole()));
        return bdNoticeVO;
    }

    @Override
    public Object[] getAdminNotice(BdNoticeVO noticeVO) {
        List<BdNoticeVO> bdNoticeVOList = new ArrayList<>();
        noticeVO.setWebsiteType(ENoticeWebsiteType.ADMIN.getValue());
        List<BdNotice> noticeList = baseMapper.getAdminNotice(noticeVO);
        if (CollUtil.isNotEmpty(noticeList)) {
            for (BdNotice notice : noticeList) {
                BdNoticeVO bdNoticeVO = BeanUtil.copyProperties(notice, BdNoticeVO.class);
                bdNoticeVO.setRoleNames(getRoleNamesTranslate(notice.getRole()));
                bdNoticeVOList.add(bdNoticeVO);
            }
        }
        return new Object[]{noticeList, bdNoticeVOList};
    }

    @Override
    public Object[] getAdminIndexNotice(BdNoticeVO noticeVO) {
        noticeVO.setWebsiteType(ENoticeWebsiteType.ADMIN.getValue());
        noticeVO.setFunctionType(ENoticeFunctionType.NOTICE.getValue());
        List<BdNotice> noticeList = baseMapper.getAdminIndexNotice(noticeVO);
        List<BdNoticeVO> bdNoticeVOList = BeanUtil.copyToList(noticeList, BdNoticeVO.class);
        return new Object[]{noticeList, bdNoticeVOList};
    }


    @Override
    public Object[] showIndexNotice(BdNoticeVO noticeVO) {
        List<BdNoticeExt> noticeList;
        Integer functionType = noticeVO.getFunctionType();
        if (functionType.equals(ENoticeFunctionType.NOTICE.getValue())) {
            noticeList = baseMapper.showIndexNotice(noticeVO);
        } else {
            noticeList = baseMapper.showIndexMailNotice(noticeVO);

        }
        List<BdNoticeVO> bdNoticeVOList = BeanUtil.copyToList(noticeList, BdNoticeVO.class);
        return new Object[]{noticeList, bdNoticeVOList};

    }

    @Override
    public List<BdNoticeVO> showIndexPopScreen(BdNoticeVO noticeVO) {
        List<BdNotice> noticeList = baseMapper.showIndexPopScreen(noticeVO);
        return BeanUtil.copyToList(noticeList, BdNoticeVO.class);
    }


    @Override
    public BdNoticeVO showIndexNoticeDetail(Long pkId, Integer pkCountry, Long pkMember) {
        BdNoticeDetail noticeDetail = iBdNoticeDetailService.selectNoticeDetailByPkNoticeId(pkId, pkMember);
        if (null == noticeDetail) {
            //保存站内信已读状态
            BdNoticeDetail detail = new BdNoticeDetail();
            detail.setPkMember(pkMember);
            detail.setPkNotice(pkId);
            detail.setReadState(EReadState.HAVE_READ.getValue());
            detail.setPkCountry(pkCountry);
            detail.setPkCreator(pkMember);
            iBdNoticeDetailService.save(detail);
        }
        BdNotice notice = baseMapper.selectById(pkId);
        return changeTranslate(notice);
    }


    @Override
    public BdNoticeVO showNoticeDetail(Long pkId) {
        BdNotice notice = baseMapper.selectById(pkId);
        return changeTranslate(notice);
    }

    /**
     * 获取等级的翻译KEY值
     *
     * @param pkId ID
     * @return Integer
     */
    @Override
    public Integer getGradeTranslateValue(Integer pkId) {
        BdGrade bdGrade = gradeService.getBdGrade(pkId);
        if (bdGrade != null) {
            return bdGrade.getPkTransaction();
        }
        return 0;
    }

    /**
     * 获取奖衔的翻译KEY值
     *
     * @param pkCountry 国家
     * @param pkId      ID
     * @return Integer
     */
    @Override
    public Integer getAwardsTranslateValue(Integer pkCountry, Integer pkId) {
        BdAwards bdAwards = awardsService.getBdAwardsOne(pkId);
        if (bdAwards != null) {
            return bdAwards.getPkTransaction();
        }
        return 0;
    }

    @Override
    public BdNoticeVO showNoticePetition(BdNoticeVO bdNoticeVO) {
        //等级翻译
        String grade = bdNoticeVO.getGrade();
        bdNoticeVO.setNoticeGradeVOList(getGradeTranslate(grade));
        //奖衔翻译
        String awards = bdNoticeVO.getAwards();
        bdNoticeVO.setAwardsVOList(getAwardTranslate(awards));
        //发布位置翻译
        String publishLocation = bdNoticeVO.getPublishLocation();
        bdNoticeVO.setLocationVOList(getLocationTranslate(publishLocation));
        //角色
        bdNoticeVO.setRoleNames(getRoleNamesTranslate(bdNoticeVO.getRole()));
        bdNoticeVO.setApprovalBusiness(getEApprovalBusiness(bdNoticeVO).getValue());
        return bdNoticeVO;
    }

    /**
     * 等级翻译
     *
     * @param grade 等级
     * @return List<DbNoticeGradeVO>
     */
    private List<DbNoticeGradeVO> getGradeTranslate(String grade) {
        DbNoticeGradeVO noticeGradeVO;
        List<DbNoticeGradeVO> noticeGradeVOList = new ArrayList<>();
        if (StringUtils.isNotEmpty(grade)) {
            String[] grades = grade.split(",");
            for (String gradeId : grades) {
                noticeGradeVO = new DbNoticeGradeVO();
                noticeGradeVO.setGradeKey(getGradeTranslateValue(Integer.parseInt(gradeId)));
                noticeGradeVOList.add(noticeGradeVO);
            }
        }
        return noticeGradeVOList;
    }

    /**
     * 等级翻译
     *
     * @param award 奖衔
     * @return List<DbNoticeAwardsVO>
     */
    private List<DbNoticeAwardsVO> getAwardTranslate(String award) {
        DbNoticeAwardsVO noticeAwardsVO;
        List<DbNoticeAwardsVO> noticeAwardList = new ArrayList<>();
        if (StringUtils.isNotEmpty(award)) {
            String[] awards = award.split(",");
            for (String awardId : awards) {
                noticeAwardsVO = new DbNoticeAwardsVO();
                noticeAwardsVO.setAwardKey(getAwardsTranslateValue(null, Integer.parseInt(awardId)));
                noticeAwardList.add(noticeAwardsVO);
            }
        }
        return noticeAwardList;
    }


    /**
     * 发布位置翻译
     *
     * @param Location 发布位置
     * @return List<DbNoticeLocationVO> locationVOList
     */
    private List<DbNoticeLocationVO> getLocationTranslate(String Location) {
        DbNoticeLocationVO noticeLocationVO;
        List<DbNoticeLocationVO> locationVOList = new ArrayList<>();
        if (StringUtils.isNotEmpty(Location)) {
            String[] Locations = Location.split(",");
            for (String locationId : Locations) {
                noticeLocationVO = new DbNoticeLocationVO();
                noticeLocationVO.setLocationKey(Integer.parseInt(locationId));
                locationVOList.add(noticeLocationVO);
            }
        }
        return locationVOList;
    }

    /**
     * 角色翻译
     *
     * @param role 角色
     * @return String
     */
    private String getRoleNamesTranslate(String role) {
        String soleTranslate = null;
        if (StringUtils.isNotEmpty(role)) {
            String[] roles = role.split(",");
            List<String> roleNames = new ArrayList<>();
            for (String roleStr : roles) {
                SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(roleStr));
                if (null != sysRole) {
                    roleNames.add(sysRole.getRoleName());
                }
            }
            soleTranslate = StringUtils.join(roleNames, ",");
        }
        return soleTranslate;
    }

    @Override
    public Integer updateNoticeByBatch(BdNotice notice) {
        return baseMapper.updateNoticeByBatch(notice);
    }

    @Override
    public Boolean deleteNoticeById(Long pkId, Long updateId) {
        UpdateWrapper<BdNotice> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq(SystemFieldConstants.PK_ID, pkId);
        updateWrapper.set(SystemFieldConstants.DEL_FLAG, EYesNo.NO.getIntValue());
        updateWrapper.set(SystemFieldConstants.PK_MODIFIED, updateId);
        updateWrapper.set(SystemFieldConstants.MODIFIED_TIME, new Date());
        return update(updateWrapper);
    }

    @Override
    public Object[] selectAdminNotice(Integer pkCountry) {
        BdNoticeAdminShowVO showVO;
        List<BdNoticeAdminShowVO> bdNoticeAdminShowVOList = new ArrayList<>();
        List<BdNoticeExt> bdNoticeExtList = baseMapper.selectAdminNotice(pkCountry);
        if (CollUtil.isNotEmpty(bdNoticeExtList)) {
            Map<String, List<BdNoticeExt>> map = bdNoticeExtList.stream().collect(Collectors.groupingBy(BdNoticeExt::getMonthTime));
            for (Map.Entry<String, List<BdNoticeExt>> entry : map.entrySet()) {
                List<BdNoticeVO> bdNoticeVOList = BeanUtil.copyToList(entry.getValue(), BdNoticeVO.class);
                showVO = new BdNoticeAdminShowVO();
                showVO.setNoticeList(bdNoticeVOList);
                showVO.setMonthTime(entry.getKey());
                bdNoticeAdminShowVOList.add(showVO);

            }
        }
        return new Object[]{bdNoticeExtList, bdNoticeAdminShowVOList};
    }

    @Override
    public Integer showIndexNoticeCount(BdNoticeVO noticeVO) {
        return baseMapper.showIndexNoticeCount(noticeVO);
    }

    @Override
    public Integer showIndexMailCount(BdNoticeVO noticeVO) {
        return baseMapper.showIndexMailCount(noticeVO);
    }


    @Override
    public List<BdNotice> selectAdminNoticeByRole(BdNoticeVO noticeVO) {
        return baseMapper.selectAdminNoticeByRole(noticeVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer upMove(Long pkId, Long sort, Long pkModified,Integer pkCountry) {
        //上条记录ID
        BdNotice upNotice = baseMapper.selectUpRecordId(pkId,pkCountry);
        if (null != upNotice) {
            //上条置顶状态
            Integer upTop = upNotice.getTop();
            BdNotice notice = baseMapper.selectById(pkId);
            //本条的置顶状态
            Integer top = notice.getTop();
            if(upTop.equals(top)){
                //交换两条记录的排序
                baseMapper.updateNoticeSortById(getBdNotice(pkId, upNotice.getSort(), pkModified, null, upNotice.getOldSort()));
                return baseMapper.updateNoticeSortById(getBdNotice(upNotice.getPkId(), sort, pkModified, null, notice.getOldSort()));
            }
        }
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer downMove(Long pkId, Long sort, Long pkModified,Integer pkCountry) {
        //下条记录ID
        BdNotice downNotice = baseMapper.selectDownRecordId(pkId,pkCountry);
        if (null != downNotice) {
            //下条置顶状态
            Integer downTop = downNotice.getTop();
            //本条记录
            BdNotice notice = baseMapper.selectById(pkId);
            //本条的置顶状态
            Integer top = notice.getTop();
            if(downTop.equals(top)){
                //交换两条记录的排序
                baseMapper.updateNoticeSortById(getBdNotice(pkId, downNotice.getSort(), pkModified, null, downNotice.getOldSort()));
                return baseMapper.updateNoticeSortById(getBdNotice(downNotice.getPkId(), sort, pkModified, null, notice.getOldSort()));
            }
        }
        return 1;
    }

    @Override
    public Integer top(Long pkId, Long sort, Long pkModified) {
        Long maxSort = baseMapper.selectMaxId();
        if (null == maxSort) {
            maxSort = MagicNumberConstants.PK_ADMIN;
        }
        return baseMapper.updateNoticeTopById(getBdNotice(pkId, maxSort + 1, pkModified, EYesNo.YES.getIntValue(), sort));
    }

    @Override
    public Integer cancelTop(Long pkId, Long sort, Long pkModified) {
        BdNotice notice = baseMapper.selectById(pkId);
        return baseMapper.updateNoticeTopById(getBdNotice(pkId, notice.getOldSort(), pkModified, EYesNo.NO.getIntValue(), sort));
    }

    private BdNotice getBdNotice(Long pkId, Long sort, Long pkModified, Integer top, Long oldSort) {
        BdNotice notice = BdNotice.builder().pkId(pkId).sort(sort).build();
        notice.setPkModified(pkModified);
        if (null != top) {
            notice.setTop(top);
        }
        if (null != oldSort) {
            notice.setOldSort(oldSort);
        }
        return notice;
    }

}
