package com.zsc.edu.gateway.modules.notice.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.exception.EmptyIdsException;
import com.zsc.edu.gateway.exception.PublishFailedException;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
import com.zsc.edu.gateway.modules.notice.dto.BulletinDto;
import com.zsc.edu.gateway.modules.notice.entity.Bulletin;
import com.zsc.edu.gateway.modules.notice.entity.BulletinAttachment;
import com.zsc.edu.gateway.modules.notice.query.BulletinQuery;
import com.zsc.edu.gateway.modules.notice.repo.BulletinRepository;
import com.zsc.edu.gateway.modules.notice.service.BulletinAttachmentService;
import com.zsc.edu.gateway.modules.notice.service.BulletinService;
import com.zsc.edu.gateway.modules.notice.vo.BulletinVo;
import com.zsc.edu.gateway.modules.system.repo.UserRepository;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

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

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

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

    private final BulletinRepository repo;
    private final BulletinAttachmentService bulletinAttachmentService;
    private final UserRepository userRepository;
    /**
     * 查询公告详情
     *
     * @param id    ID
     * @param state 公告状态
     * @return 公告详情
     */
    @Override
    public List<BulletinVo> detail(UserDetailsImpl userDetails, Long id, Bulletin.State state) {
        List<BulletinVo> bulletins = repo.selectByBulletinId(id);
        if (bulletins.isEmpty()) {
            return Collections.emptyList();
        }
        for (BulletinVo bulletin : bulletins) {
            if (state != null) {
                bulletin.getState().checkStatus(state);
            }
            bulletin.setEditUsername(userRepository.selectNameById(bulletin.getEditUserId()));
            bulletin.setPublishUsername(userRepository.selectNameById(bulletin.getPublishUserId()));
            bulletin.setCloseUsername(userRepository.selectNameById(bulletin.getCloseUserId()));
        }

        return bulletins;
    }
    /**
     * 新建公告
     *
     * @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=new Bulletin();
        BeanUtils.copyProperties(dto,bulletin);
        bulletin.setCreateTime(LocalDateTime.now());
        bulletin.setCreateBy(userDetails.getName());
        bulletin.setEditUserId(userDetails.getId());
        save(bulletin);
        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));
        BeanUtils.copyProperties(dto, bulletin);
        bulletin.setCreateBy(userDetails.getName());
        bulletin.setCreateTime(LocalDateTime.now());
        bulletin.state = edit;
        return updateById(bulletin);
    }
    /**
     * 发布公告，只能发布"编辑中"的公告
     *
     * @param userDetails 操作用户
     * @param ids          ids
     * @return 已发布的公告
     */
    @Override
    public List<String> publish(UserDetailsImpl userDetails, List<Long> ids)throws PublishFailedException, EmptyIdsException {
        List<String> results=new ArrayList<>();
        if (ids == null || ids.isEmpty()) {
            throw new EmptyIdsException("您输入的集合为空");
        }
        List<Bulletin> bulletins=getBulletinsByIds(ids);
        for (Bulletin bulletin : bulletins) {
            try {
                bulletin.state.checkStatus(EnumSet.of(edit));
            } catch (Exception e) {
                throw new PublishFailedException("发布失败: " + e.getMessage());
            }
        }
        for(Bulletin bulletin:bulletins){
            try{
                bulletin.state = publish;
                bulletin.setPublishUserId(userDetails.getId());
                bulletin.setPublishTime(LocalDateTime.now());
                boolean result=updateById(bulletin);
                if(result){
                    results.add("发布成功");
                }else {
                    throw new PublishFailedException("发布失败");
                }
            }catch(Exception e){
                throw new PublishFailedException("发布失败: " + e.getMessage());
            }
        }
        return results;
    }

    /**
     * 切换关闭状态，只能关闭"已发布"的公告，只能开启“已关闭”的公告
     *
     * @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.checkStatus(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
     * @return true
     */
    @Override
    public Boolean insertInto(Long bulletinId, Set<String> attachmentIds) {
        List<BulletinAttachment> bulletinAttachments = attachmentIds.stream()
                .map(attachmentId -> new BulletinAttachment(bulletinId, attachmentId))
                .collect(Collectors.toList());
        return bulletinAttachmentService.saveBatch(bulletinAttachments);
    }


    private List<Bulletin> getBulletinsByIds(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<Bulletin> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.in(Bulletin::getId, ids);
        return repo.selectList(queryWrapper);
    }

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