package cn.wisenergy.chnmuseum.party.service.impl;

import cn.wisenergy.chnmuseum.party.common.enums.AuditOperationEnum;
import cn.wisenergy.chnmuseum.party.common.enums.AuditStatusEnum;
import cn.wisenergy.chnmuseum.party.common.enums.AuditTypeEnum;
import cn.wisenergy.chnmuseum.party.common.mvc.InterfaceException;
import cn.wisenergy.chnmuseum.party.mapper.AuditMapper;
import cn.wisenergy.chnmuseum.party.model.*;
import cn.wisenergy.chnmuseum.party.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <pre>
 * 学习内容信息 服务实现类
 * </pre>
 *
 * @author Danny Lee
 * @since 2021-03-26
 */
@Slf4j
@Service
public class AuditServiceImpl extends ServiceImpl<AuditMapper, Audit> implements AuditService {

    @Resource
    private AuditMapper auditMapper;

    @Resource
    private TUserServiceImpl userService;

    @Resource
    private VideoContentService videoContentService;

    @Resource
    private ExhibitionBoardService exhibitionBoardService;

    @Resource
    private LearningContentService learningContentService;

    @Resource
    private LearningContentBoardService learningContentBoardService;

    @Override
    public Page<Audit> getUserList(Page<Audit> page, TUser user) {
        return page.setRecords(auditMapper.getUserList(page, user));
    }

    /**
     * 分页查询
     *
     * @param name
     * @param status
     * @param type
     * @return
     */
    @Override
    public Page<Audit> pageList(String name, AuditStatusEnum status, AuditStatusEnum auditStatusLevel, AuditTypeEnum type, Page<Object> page) {
        //分页
        Page<Audit> auditPage = new Page<>();
        auditPage.setCurrent(page.getCurrent());
        auditPage.setSize(page.getSize());
        //条件
        QueryWrapper<Audit> ew = new QueryWrapper<Audit>()
                //暂时注掉
//                .eq("a.level", auditStatusLevel.name())
                .eq("a.type", type.name())
                .eq("a.is_deleted", 0)
//                .eq("b.is_deleted", 0)
//                .eq("c.is_deleted", 0)
                .orderByDesc("a.create_time", "a.id");
        //
        if (status != null) {
            ew.eq(status != null, "a.status", status.name());
        }
        Page<Audit> pageList = pageByType(ew, name, type, auditPage);
        return pageList;
    }

    /**
     * 分别查询
     *
     * @param name
     * @param type
     * @param auditPage
     * @return
     */
    private Page<Audit> pageByType(QueryWrapper<Audit> ew, String name,
                                   AuditTypeEnum type, Page<Audit> auditPage) {
        Page<Audit> selectPage = null;
        if (StringUtils.isNotBlank(name)) {
            ew.and(i -> i.like("b.name", name).or().like("c.user_name", name));
        }
        switch (type) {
            case LEARNING_CONTENT:
                selectPage = auditMapper.getLearningContentPage(auditPage, ew);
                break;
            case EXHIBITION_BOARD:
                selectPage = auditMapper.getExhibitionBoardPage(auditPage, ew);
                break;
            case ACCOUNT:
                break;
            case VIDEO_CONTENT:
                selectPage = auditMapper.getVideoContentPage(auditPage, ew);
            default:
        }
        //
        return selectPage;
    }

    /**
     * 根据id更新审核信息
     *
     * @param audit
     * @return
     */
    @Override
    public boolean updateAuditAllById(Audit audit) {
        //审核层级,初审 和 复审
        AuditStatusEnum auditStatusLevel = AuditStatusEnum.valueOf(audit.getLevel());
        boolean update;
        switch (auditStatusLevel) {
            case TBC:
                update = updateOnTBC(audit);
                return update;
            case TBCA:
                update = updateOnTBCA(audit);
                return update;
            default:
                throw new InterfaceException("level参数不正确");
        }
    }

    @Override
    public Audit selectOne(String id, String type) {
        UpdateWrapper<Audit> wrapper = new UpdateWrapper<>();
        if (StringUtils.isNotBlank(id)) {
            wrapper.eq("ref_item_id", id);
        }
        if (StringUtils.isNotBlank(type)) {
            wrapper.eq("type", type);
        }
        wrapper.orderByDesc("create_time").last("limit 1");
        return getOne(wrapper);
    }

    /**
     * 初审级别的修改情况
     *
     * @return
     */
    private boolean updateOnTBC(Audit audit) {
        audit.setFirstTime(LocalDateTime.now());
        String status = audit.getStatus();
        AuditStatusEnum auditStatusEnum = AuditStatusEnum.valueOf(status);
        //初审 通过时,修改状态为待复审
        if (AuditStatusEnum.APPROVED_FINAL.equals(auditStatusEnum)) {
            audit.setStatus(AuditStatusEnum.TBCA.name());
            audit.setLevel(AuditStatusEnum.TBCA.name());
        }
        if (!AuditStatusEnum.REFUSED.equals(auditStatusEnum)) {
            audit.setFirstRemarks("");
        }
        audit.setSecondRemarks("");
        //通过与不通过时 都修改
        boolean updateRefItemByRefItemId = updateRefItemByRefItemId(audit);
        int update = auditMapper.updateById(audit);
        return updateRefItemByRefItemId && update >= 1;
        //初审驳回时,不做状态修改
//        int update = auditMapper.updateById(audit);
//        return update >= 1;
    }

    /**
     * 复审级别的修改情况
     *
     * @return
     */
    private boolean updateOnTBCA(Audit audit) {
        audit.setSecondTime(LocalDateTime.now());
        String status = audit.getStatus();
        AuditStatusEnum auditStatusEnum = AuditStatusEnum.valueOf(status);
        if (!AuditStatusEnum.REFUSED.equals(auditStatusEnum)) {
            audit.setSecondRemarks("");
        }
        audit.setFirstRemarks("");
        //复审通过时,
//        boolean updateRefItemByRefItemId = true;
//        if (AuditStatusEnum.APPROVED_FINAL.equals(auditStatusEnum)) {
//            //修改对应审核项中的信息
//            updateRefItemByRefItemId = updateRefItemByRefItemId(audit);
//        }

        //通过与不通过时 都修改
        boolean updateRefItemByRefItemId = updateRefItemByRefItemId(audit);
        int update = auditMapper.updateById(audit);
        return updateRefItemByRefItemId && update >= 1;
    }

    /**
     * 根据审核项ID 修改 审核项表中的信息
     */
    private boolean updateRefItemByRefItemId(Audit audit) {
        String type = audit.getType();
        AuditTypeEnum auditTypeEnum = AuditTypeEnum.valueOf(type);
        boolean update;
        switch (auditTypeEnum) {
            case VIDEO_CONTENT:
                update = fillVideoContentByAudit(audit);
                break;
//            case ACCOUNT:
//                break;
            case EXHIBITION_BOARD:
                update = fillExhibitionBoardByAudit(audit);
                break;
            case LEARNING_CONTENT:
                update = fillLearningContentByAudit(audit);
                break;
            default:
                throw new InterfaceException("type参数不正确");
        }
        return update;
    }

    /**
     * 根据审核操作 填充VideoContent属性用于更改
     *
     * @param audit
     * @return
     */
    public boolean fillVideoContentByAudit(Audit audit) {
        VideoContent videoContent = new VideoContent();
        videoContent.setId(audit.getRefItemId());
        videoContent.setAuditStatus(audit.getStatus());
        //当审核级别为复审,审核状态为通过是,会修改审核项其它表中的 发布与删除字段,不是此情况下是直接修改审核状态
        boolean continueFill = AuditStatusEnum.APPROVED_FINAL.name().equals(audit.getStatus()) && AuditStatusEnum.TBCA.name().equals(audit.getLevel());
        if (!continueFill) {
            return this.videoContentService.updateById(videoContent);
        }
        String operation = audit.getOperation();
        AuditOperationEnum auditOperationEnum = AuditOperationEnum.valueOf(operation);
        boolean update = false;
        switch (auditOperationEnum) {
            case ENABLE:
                videoContent.setPublished(true);
                update = this.videoContentService.updateById(videoContent);
                break;
            case DISABLE:
                videoContent.setPublished(false);
                update = this.videoContentService.updateById(videoContent);
                break;
            case REMOVE:
                final LambdaQueryWrapper<ExhibitionBoard> queryWrapper = Wrappers.<ExhibitionBoard>lambdaQuery().eq(ExhibitionBoard::getVideoContentId, videoContent.getId());
                queryWrapper.select(ExhibitionBoard::getId);
                final List<String> ExhibitionBoardIdList = this.exhibitionBoardService.listObjs(queryWrapper, Object::toString);
                this.exhibitionBoardService.removeByIds(ExhibitionBoardIdList);
                update = this.videoContentService.removeById(videoContent);
                break;
            case ADD:
                videoContent.setPublished(true);
                update = this.videoContentService.updateById(videoContent);;
                break;
            case EDIT:
                videoContent.setPublished(true);
                update = this.videoContentService.updateById(videoContent);;
                break;
            default:
        }
        return update;
    }

    /**
     * 根据审核操作 填充ExhibitionBoard属性用于更改
     *
     * @param audit
     * @return
     */
    public boolean fillExhibitionBoardByAudit(Audit audit) {
        ExhibitionBoard exhibitionBoard = new ExhibitionBoard();
        exhibitionBoard.setId(audit.getRefItemId());
        exhibitionBoard.setAuditStatus(audit.getStatus());
        //当审核级别为复审,审核状态为通过是,会修改审核项其它表中的 发布与删除字段,不是此情况下是直接修改审核状态
        boolean continueFill = AuditStatusEnum.APPROVED_FINAL.name().equals(audit.getStatus()) && AuditStatusEnum.TBCA.name().equals(audit.getLevel());
        if (!continueFill) {
            return this.exhibitionBoardService.updateById(exhibitionBoard);
        }
        String operation = audit.getOperation();
        AuditOperationEnum auditOperationEnum = AuditOperationEnum.valueOf(operation);
        boolean update = false;
        switch (auditOperationEnum) {
            case UPPER:
                exhibitionBoard.setPublished(true);
                update = this.exhibitionBoardService.updateById(exhibitionBoard);
                break;
            case LOWER:
                exhibitionBoard.setPublished(false);
                update = this.exhibitionBoardService.updateById(exhibitionBoard);
                break;
            case REMOVE:
                this.learningContentBoardService.remove(Wrappers.<LearningContentBoard>lambdaUpdate().eq(LearningContentBoard::getExhibitionBoardId, exhibitionBoard.getId()));
                update = this.exhibitionBoardService.removeById(exhibitionBoard);
                break;
            case ADD:
                exhibitionBoard.setPublished(true);
                update = this.exhibitionBoardService.updateById(exhibitionBoard);;
                break;
            case EDIT:
                exhibitionBoard.setPublished(true);
                update = this.exhibitionBoardService.updateById(exhibitionBoard);;
                break;
            default:
        }
        return update;
    }

    /**
     * 根据审核操作 填充LearningContent属性用于更改
     *
     * @param audit
     * @return
     */
    public boolean fillLearningContentByAudit(Audit audit) {
        LearningContent learningContent = new LearningContent();
        learningContent.setAuditStatus(audit.getStatus());
        learningContent.setId(audit.getRefItemId());
        //当审核级别为复审,审核状态为通过是,会修改审核项其它表中的 发布与删除字段,不是此情况下是直接修改审核状态
        boolean continueFill = AuditStatusEnum.APPROVED_FINAL.name().equals(audit.getStatus()) && AuditStatusEnum.TBCA.name().equals(audit.getLevel());
        if (!continueFill) {
            return this.learningContentService.updateById(learningContent);
        }
        String operation = audit.getOperation();
        AuditOperationEnum auditOperationEnum = AuditOperationEnum.valueOf(operation);
        boolean update = false;
        switch (auditOperationEnum) {
            case ENABLE:
                learningContent.setPublished(true);
                update = this.learningContentService.updateById(learningContent);
                break;
            case DISABLE:
                learningContent.setPublished(false);
                update = this.learningContentService.updateById(learningContent);
                break;
            case REMOVE:
                update = this.learningContentService.removeById(learningContent);
                break;
            case ADD:
                learningContent.setPublished(true);
                update = this.learningContentService.updateById(learningContent);
                break;
            case EDIT:
                learningContent.setPublished(true);
                update = this.learningContentService.updateById(learningContent);
                break;
            default:
        }
        return update;
    }

    /**
     * 根据审核项数据插入审核记录
     *
     * @param refItemId     审核项ID
     * @param content       审核内容
     * @param typeEnum      审核类型
     * @param operationEnum 操作类型
     * @return
     */
    @Override
    public boolean saveByRefItemInfo(String refItemId, String content, AuditTypeEnum typeEnum, AuditOperationEnum operationEnum) {
        Audit audit = new Audit();
        //
        audit.setRefItemId(refItemId);
        audit.setContent(content);
        audit.setType(typeEnum.name());
        audit.setOperation(operationEnum.name());
        //
        audit.setLevel(AuditStatusEnum.TBC.name());
        audit.setStatus(AuditStatusEnum.TBC.name());
        audit.setDeleted(false);
        audit.setCreateTime(LocalDateTime.now());
        //
        Object principal = SecurityUtils.getSubject().getPrincipal();
        if (principal instanceof TUser) {
            TUser user = (TUser) principal;
            audit.setUserId(user.getId());
            audit.setUserName(user.getUserName());
            audit.setOrganId(user.getOrgId());
            audit.setOrgName(user.getOrgName());
        }
        //保存
        int insert = auditMapper.insert(audit);
        return insert >= 1;
    }

}