package com.haha.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.haha.common.constant.AnnouncementConstants;
import com.haha.common.constant.CommonConstants;
import com.haha.entity.dto.AnnouncementQueryDTO;
import com.haha.entity.Announcement;
import com.haha.mapper.AnnouncementMapper;
import com.haha.service.AnnouncementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 系统公告服务实现类
 */
@Slf4j
@Service
public class AnnouncementServiceImpl extends ServiceImpl<AnnouncementMapper, Announcement>
        implements AnnouncementService {

    @Autowired
    private AnnouncementMapper announcementMapper;

    // 公告类型
    public static final int TYPE_SYSTEM = 1;      // 系统公告
    public static final int TYPE_ACTIVITY = 2;    // 活动公告
    public static final int TYPE_MAINTENANCE = 3; // 维护公告
    public static final int TYPE_OTHER = 4;       // 其他

    @Override
    public IPage<Announcement> getPage(int page, int pageSize, AnnouncementQueryDTO queryDTO) {
        LambdaQueryWrapper<Announcement> wrapper = new LambdaQueryWrapper<>();

        // 标题搜索
        if (StringUtils.hasText(queryDTO.getTitle())) {
            wrapper.like(Announcement::getTitle, queryDTO.getTitle());
        }

        // 类型筛选
        if (queryDTO.getType() != null) {
            wrapper.eq(Announcement::getType, queryDTO.getType());
        }

        // 状态筛选
        if (queryDTO.getStatus() != null) {
            wrapper.eq(Announcement::getStatus, queryDTO.getStatus());
        }

        // 按置顶和创建时间倒序
        wrapper.orderByDesc(Announcement::getIsTop)
               .orderByDesc(Announcement::getCreateTime);

        IPage<Announcement> pageResult = page(new Page<>(page, pageSize), wrapper);

        // 填充展示字段
        for (Announcement announcement : pageResult.getRecords()) {
            fillLabels(announcement);
        }

        return pageResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publish(Long id, Long publisherId, String publisherName) {
        Announcement announcement = getById(id);
        if (announcement == null) {
            return false;
        }

        announcement.setStatus(AnnouncementConstants.STATUS_PUBLISHED);
        announcement.setPublishTime(LocalDateTime.now());
        announcement.setPublisherId(publisherId);
        announcement.setPublisherName(publisherName);
        announcement.setUpdateTime(LocalDateTime.now());

        return updateById(announcement);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean offline(Long id) {
        Announcement announcement = getById(id);
        if (announcement == null) {
            return false;
        }

        announcement.setStatus(AnnouncementConstants.STATUS_OFFLINE);
        announcement.setOfflineTime(LocalDateTime.now());
        announcement.setUpdateTime(LocalDateTime.now());

        return updateById(announcement);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setTop(Long id, Integer isTop) {
        Announcement announcement = getById(id);
        if (announcement == null) {
            return false;
        }

        announcement.setIsTop(isTop);
        announcement.setUpdateTime(LocalDateTime.now());

        return updateById(announcement);
    }

    @Override
    public List<Announcement> getAppList(int limit) {
        if (limit <= 0 || limit > CommonConstants.MAX_PAGE_SIZE) {
            limit = CommonConstants.DEFAULT_PAGE_SIZE;
        }

        LambdaQueryWrapper<Announcement> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Announcement::getStatus, AnnouncementConstants.STATUS_PUBLISHED)
               .orderByDesc(Announcement::getIsTop)
               .orderByDesc(Announcement::getPublishTime);

        IPage<Announcement> pageResult = page(new Page<>(1, limit), wrapper);
        for (Announcement announcement : pageResult.getRecords()) {
            fillLabels(announcement);
        }

        return pageResult.getRecords();
    }

    @Override
    public Announcement getDetail(Long id) {
        Announcement announcement = getById(id);
        if (announcement != null) {
            // 增加阅读次数
            announcementMapper.incrementReadCount(id);
            fillLabels(announcement);
        }
        return announcement;
    }

    /**
     * 填充展示字段
     */
    private void fillLabels(Announcement announcement) {
        // 公告类型
        switch (announcement.getType()) {
            case TYPE_SYSTEM:
                announcement.setTypeLabel("系统公告");
                announcement.setTypeColor("primary");
                break;
            case TYPE_ACTIVITY:
                announcement.setTypeLabel("活动公告");
                announcement.setTypeColor("success");
                break;
            case TYPE_MAINTENANCE:
                announcement.setTypeLabel("维护公告");
                announcement.setTypeColor("warning");
                break;
            default:
                announcement.setTypeLabel("其他");
                announcement.setTypeColor("info");
        }

        // 公告状态
        switch (announcement.getStatus()) {
            case AnnouncementConstants.STATUS_DRAFT:
                announcement.setStatusLabel("草稿");
                announcement.setStatusColor("info");
                break;
            case AnnouncementConstants.STATUS_PUBLISHED:
                announcement.setStatusLabel("已发布");
                announcement.setStatusColor("success");
                break;
            case AnnouncementConstants.STATUS_OFFLINE:
                announcement.setStatusLabel("已下线");
                announcement.setStatusColor("danger");
                break;
        }
    }
}
