package com.zsc.edu.gateway.modules.message.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsc.edu.gateway.exception.ConstraintException;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
import com.zsc.edu.gateway.modules.message.dto.BulletinDto;
import com.zsc.edu.gateway.modules.message.entity.Bulletin;
import com.zsc.edu.gateway.modules.message.entity.BulletinAttachment;
import com.zsc.edu.gateway.modules.message.mapper.BulletinMapper;
import com.zsc.edu.gateway.modules.message.query.BulletinQuery;
import com.zsc.edu.gateway.modules.message.repo.BulletinAttachmentRepository;
import com.zsc.edu.gateway.modules.message.repo.BulletinRepository;
import com.zsc.edu.gateway.modules.message.service.BulletinService;
import com.zsc.edu.gateway.modules.message.vo.BulletinVo;
import com.zsc.edu.gateway.modules.system.repo.UserRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

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

import static com.zsc.edu.gateway.modules.message.entity.Bulletin.State.*;

/**
 * 系统公告Service
 *
 * @author harry_yao
 */
@AllArgsConstructor
@Service
public class BulletinServiceImpl extends ServiceImpl<BulletinRepository, Bulletin> implements BulletinService {

    private final BulletinMapper mapper;
    private final BulletinRepository repo;
    private final BulletinAttachmentRepository bulletinAttachmentRepository;
    /**
     * 查询公告详情
     *
     * @param id    ID
     * @param state 公告状态
     * @return 公告详情
     */
    @Override
    public BulletinVo detail(UserDetailsImpl userDetails, Long id, Bulletin.State state) {
        BulletinVo bulletinVo = repo.selectByBulletinId(id);
        if (state != null) {
            bulletinVo.getState().checkStatus(state);
        }
        bulletinVo.setEditUsername(UserRepository.selectNameById(bulletinVo.getEditUserId()));
        bulletinVo.setPublishUsername(UserRepository.selectNameById(bulletinVo.getPublishUserId()));
        bulletinVo.setCloseUsername(UserRepository.selectNameById(bulletinVo.getCloseUserId()));
        return bulletinVo;
    }
    /**
     * 新建公告
     *
     * @param userDetails 操作用户
     * @param dto         表单数据
     * @return 新建的公告
     */
    @Override
    public Bulletin create(UserDetailsImpl userDetails, BulletinDto dto) {
        boolean existsByName=count(new LambdaQueryWrapper<Bulletin>().eq(Bulletin::getTitle,dto.getTitle())) > 0;
        if(existsByName){
            throw new ConstraintException("title", dto.title, "标题已存在");
        }
        Bulletin bulletin = mapper.toEntity(dto);
        bulletin.setEditUserId(userDetails.getId());
        save(bulletin);
        if (dto.getAttachmentIds() != null) {
            insertInto(bulletin.getId(), dto.getAttachmentIds());
        }
        return bulletin;
    }
    /**
     * 修改公告，只能修改"编辑中"或"已发布"的公告
     *
     * @param userDetails 操作用户
     * @param dto         表单数据
     * @return 已修改的公告
     */
    @Override
    public Boolean update(UserDetailsImpl userDetails,BulletinDto dto, Long id) {
        Bulletin bulletin = getById(id);
        bulletin.state.checkStatus(EnumSet.of(edit, publish));
        mapper.convert(dto, bulletin);
        bulletin.setCreateBy(userDetails.getName());
        bulletin.setCreateTime(LocalDateTime.now());
        bulletin.state = edit;
        if (dto.getAttachmentIds() != null) {
            LambdaQueryWrapper<BulletinAttachment> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BulletinAttachment::getBulletinId, bulletin.getId());
            bulletinAttachmentRepository.delete(queryWrapper);
            insertInto(bulletin.getId(), dto.getAttachmentIds());
        }
        return updateById(bulletin);
    }
    /**
     * 批量发布公告，只能发布"编辑中"的公告
     *
     * @param userDetails 操作用户
     * @param ids         ids
     * @return 已发布的公告
     */
    @Override
    public boolean publish(UserDetailsImpl userDetails, List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new RuntimeException("您输入的集合为空");
        }
        LambdaQueryWrapper<Bulletin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Bulletin::getId, ids);
        List<Bulletin> bulletins = repo.selectList(queryWrapper);
        boolean allEditable = true;
        for (Bulletin bulletin : bulletins) {
            try {
                bulletin.state.checkStatus(EnumSet.of(edit));
            } catch (Exception e) {
                allEditable = false;
                break;
            }
        }
        if (!allEditable) {
            throw new RuntimeException("存在公告状态不是编辑中的，无法发布");
        }
        return this.lambdaUpdate().in(Bulletin::getId, ids)
                .eq(Bulletin::getState, edit)
                .set(Bulletin::getState, publish)
                .set(Bulletin::getPublishTime, LocalDateTime.now())
                .set(Bulletin::getPublishUserId, userDetails.getId())
                .update();
    }

    /**
     * 切换关闭状态，只能关闭"已发布"的公告，只能开启“已关闭”的公告
     *
     * @param userDetails 操作用户
     * @param id          ID
     * @return 已关闭的公告
     */
    @Override
    public Boolean close(UserDetailsImpl userDetails, Long id) {
        Bulletin bulletin = getById(id);
        bulletin.top = false;
        if(bulletin.state==close){
            bulletin.state = edit;
            return updateById(bulletin);
        }
        bulletin.state.checkStatus(publish);
        bulletin.state = close;
        bulletin.setCloseUserId(userDetails.getId());
        bulletin.setCloseTime(LocalDateTime.now());
        return updateById(bulletin);
    }

    /**
     * 切换公告置顶状态
     *
     * @param id ID
     * @return 被更新的公告
     */
    @Override
    public Boolean toggleTop(Long id) {
        Bulletin bulletin = getById(id);
        bulletin.top = !bulletin.top;
        return updateById(bulletin);
    }

    /**
     *为公告添加附件
     *
     * @param bulletinId bulletinId
     * @param attachmentIds attachments
     */
    public void insertInto(Long bulletinId, List<String> attachmentIds) {
        List<BulletinAttachment> bulletinAttachments = attachmentIds.stream()
                .map(attachmentId -> new BulletinAttachment(bulletinId, attachmentId))
                .collect(Collectors.toList());
        bulletinAttachmentRepository.insert(bulletinAttachments);
    }

    @Override
    public IPage<BulletinVo> selectPageByConditions(Page<BulletinVo> page, BulletinQuery query) {
        return baseMapper.selectPageByConditions(page, query);
    }

    @Override
    public Boolean delete(Long id) {
        LambdaQueryWrapper<BulletinAttachment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BulletinAttachment::getBulletinId, id);
        List<BulletinAttachment> bulletinAttachments = bulletinAttachmentRepository.selectList(queryWrapper);
        if (!bulletinAttachments.isEmpty()) {
            bulletinAttachmentRepository.delete(queryWrapper);
        }
        return removeById(id);
    }
}
