package com.cf.imes.module.system.service.notice;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.framework.organ.core.aop.OrganIgnore;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.controller.admin.notice.vo.NoticePageReqVO;
import com.cf.imes.module.system.controller.admin.notice.vo.NoticeSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.notice.NoticeDO;
import com.cf.imes.module.system.dal.mysql.notice.NoticeMapper;
import com.cf.imes.module.system.enums.ErrorCodeConstants;
import com.cf.imes.module.system.enums.notice.NoticeSourceEnum;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;

import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.NOTICE_NAME_UNIQE_ERROR;

/**
 * 通知公告 Service 实现类
 *
 * @author 晨丰科技
 */
@Service
public class NoticeServiceImpl implements NoticeService {

    @Resource
    private NoticeMapper noticeMapper;


    private NoticeServiceImpl getSelf() {
        return SpringUtil.getBean(getClass());
    }

    @Override
    public Long createNotice(NoticeSaveReqVO createReqVO) {
        // 标题唯一性校验
        validateNameExists(createReqVO);
        NoticeDO notice = BeanUtils.toBean(createReqVO, NoticeDO.class);

        // 超管创建的都是内置公告
        modifySource(notice);
        noticeMapper.insert(notice);
        return notice.getId();
    }

    @Override
    public void updateNotice(NoticeSaveReqVO updateReqVO) {
        // 校验是否存在
        getSelf().validateNoticeExists(updateReqVO.getId());
        // 标题唯一性校验
        getSelf().validateNameExists(updateReqVO);
        // 更新通知公告
        NoticeDO updateObj = BeanUtils.toBean(updateReqVO, NoticeDO.class);
        noticeMapper.updateById(updateObj);
    }

    @Override
    public void deleteNotice(Long id) {
        // 校验是否存在
        getSelf().validateNoticeExists(id);
        // 删除通知公告
        noticeMapper.deleteById(id);
    }

    @Override
    public PageResult<NoticeDO> getNoticePage(NoticePageReqVO reqVO) {
        return noticeMapper.selectPage(reqVO, new LambdaQueryWrapperX<NoticeDO>()
                .likeIfPresent(NoticeDO::getTitle, reqVO.getTitle())
                .eqIfPresent(NoticeDO::getStatus, reqVO.getStatus())
                .orderByDesc(NoticeDO::getId));
    }

    @Override
    @OrganIgnore
    public PageResult<NoticeDO> getHomePageNoticePage(NoticePageReqVO reqVO) {
        return noticeMapper.selectHomePageNoticePage(reqVO);
    }

    @Override
    public NoticeDO getNotice(Long id) {
        return noticeMapper.selectById(id);
    }

    @OrganIgnore
    public void validateNoticeExists(Long id) {
        if (id == null) {
            return;
        }
        NoticeDO notice = noticeMapper.selectById(id);
        if (notice == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.NOTICE_NOT_FOUND);
        }
        boolean superAdmin = SecurityFrameworkUtils.isSuperAdmin();
        // 公告和操作人非统一组织，只有超管可以编辑和删除
        if (NoticeSourceEnum.CUSTOM.equals(notice.getSource())
                && !notice.getOrganId().equals(OrganContextHolder.getOrganId())
                && !superAdmin) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.NOTICE_NOT_FOUND);
        }
        // 只有超管可以操作内置公告
        if (NoticeSourceEnum.SYSTEM.equals(notice.getSource()) && !superAdmin) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.NOTICE_BUILDIN_MODIFY_PERMISSION_ERROR);
        }
    }

    /**
     * 校验公告标题唯一性
     *
     * @param reqVO
     */
    @OrganIgnore
    public void validateNameExists(NoticeSaveReqVO reqVO) {
        boolean isSuperAdmin = SecurityFrameworkUtils.isSuperAdmin();

        Long noticeId = reqVO.getId();
        LambdaQueryWrapper<NoticeDO> wrapper = new LambdaQueryWrapperX<NoticeDO>().eq(NoticeDO::getTitle, reqVO.getTitle());
        if (ObjectUtil.isNotNull(noticeId)) {
            wrapper.ne(NoticeDO::getId, noticeId);
        }
        if (isSuperAdmin) {
            wrapper.eq(NoticeDO::getSource, NoticeSourceEnum.SYSTEM);
        } else {
            wrapper.eq(NoticeDO::getOrganId, OrganContextHolder.getOrganId());
        }
        if (noticeMapper.exists(wrapper)) {
            throw exception(NOTICE_NAME_UNIQE_ERROR);
        }
    }

    /**
     * 公告来源赋值
     *
     * @param notice
     */
    private void modifySource(NoticeDO notice) {
        if (SecurityFrameworkUtils.isSuperAdmin()) {
            notice.setSource(NoticeSourceEnum.SYSTEM);
        } else {
            notice.setSource(NoticeSourceEnum.CUSTOM);
        }
    }
}
