package jnpf.notice.controller.app;


import cn.hutool.core.bean.BeanUtil;
import com.github.pagehelper.PageInfo;
import jnpf.base.ActionResult;
import jnpf.base.vo.PageListVO;
import jnpf.model.notice.domain.FtbNoticeAnnouncements;
import jnpf.model.notice.domain.FtbNoticeCategories;
import jnpf.model.notice.dto.FtbNoticeAnnouncementsDetailDto;
import jnpf.model.notice.dto.FtbNoticeAnnouncementsDto;
import jnpf.model.notice.dto.FtbNoticeAnnouncementsReceiveDto;
import jnpf.model.notice.enums.NoticeEnums;
import jnpf.model.notice.req.announcement.AddNoticeAnnouncementsReq;
import jnpf.model.notice.req.announcement.AppQueryAnnouncementListReq;
import jnpf.model.notice.req.announcement.QueryUserListReq;
import jnpf.model.notice.req.announcement.UpdateNoticeAnnouncementsReq;
import jnpf.notice.service.FtbNoticeAnnouncementsReceiveService;
import jnpf.notice.service.FtbNoticeAnnouncementsService;
import jnpf.notice.service.FtbNoticeCategoriesService;
import jnpf.notice.utils.NoticeUtils;
import jnpf.util.FtbUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * app公告模块
 *
 * @author xgl
 * @since 2024-05-08 09:51:26
 */
@Slf4j
@RestController
@RequestMapping("/app/noticeAnnouncements")
public class AppNoticeAnnouncementsController {
    /**
     * 服务对象
     */
    @Autowired
    private FtbNoticeAnnouncementsService ftbNoticeAnnouncementsService;

    @Autowired
    private FtbNoticeAnnouncementsReceiveService ftbNoticeAnnouncementsReceiveService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private FtbNoticeCategoriesService ftbNoticeCategoriesService;

    /**
     * 查询公告列表
     *
     * @param req
     * @return {@link ActionResult}<{@link FtbNoticeAnnouncementsDto}>
     */
    @GetMapping("/queryList")
    public ActionResult<PageListVO<FtbNoticeAnnouncementsDto>> pageLists(@Validated AppQueryAnnouncementListReq req) {
        PageInfo<FtbNoticeAnnouncementsDto> pageVo = ftbNoticeAnnouncementsService.getAppPageList(req);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }


    /**
     * 添加公告
     *
     * @param req 参数
     * @return {@link ActionResult}<{@link String}>
     */
    @PostMapping("/add")
    public ActionResult<FtbNoticeAnnouncementsDetailDto> add(@Validated @RequestBody AddNoticeAnnouncementsReq req) {
        FtbNoticeAnnouncements entity = ftbNoticeAnnouncementsService.insertData(req);
        FtbNoticeAnnouncementsDetailDto dto = BeanUtil.copyProperties(entity, FtbNoticeAnnouncementsDetailDto.class);
        FtbNoticeCategories categories = ftbNoticeCategoriesService.getById(req.getCategoryId());
        if(null !=categories){
            dto.setCategoryName(categories.getName());
        }
        if (req.getOptionBtn().equals(NoticeEnums.OptionButtonType.DRAFT.getCode())) {
            return ActionResult.success("保存成功", dto);
        } else {
            return ActionResult.success("发布成功", dto);
        }
    }


    /**
     * 编辑公告
     *
     * @param id  公告主键ID，必传
     * @param req
     * @return {@link ActionResult}
     */
    @PutMapping("/update/{id}")
    public ActionResult<FtbNoticeAnnouncementsDetailDto> update(@PathVariable("id") String id, @Validated @RequestBody UpdateNoticeAnnouncementsReq req) {
        String lockKey = String.format(NoticeUtils.NOTICE_UPDATE_KEY, id);
        if (redisTemplate.opsForValue().setIfAbsent(lockKey, UUID.randomUUID().toString(), NoticeUtils.NOTICE_UPDATE_MAX_TIME, TimeUnit.SECONDS)) {
            try {
                FtbNoticeAnnouncements entity = ftbNoticeAnnouncementsService.updateData(id, req);
                FtbNoticeAnnouncementsDetailDto dto = BeanUtil.copyProperties(entity, FtbNoticeAnnouncementsDetailDto.class);
                FtbNoticeCategories categories = ftbNoticeCategoriesService.getById(req.getCategoryId());
                if(null !=categories){
                    dto.setCategoryName(categories.getName());
                }
                if (req.getOptionBtn().equals(NoticeEnums.OptionButtonType.DRAFT.getCode())) {
                    return ActionResult.success("保存成功", dto);
                } else {
                    return ActionResult.success("发布成功", dto);
                }
            } catch (Exception e) {
                log.error("编辑公告失败", e);
                return ActionResult.fail(e.getMessage());
            } finally {
                redisTemplate.delete(lockKey);
            }
        } else {
            throw new RuntimeException("提交中,请稍候");
        }
    }


    /**
     * 查询详情
     *
     * @param id 公告主键ID，必传
     * @return {@link ActionResult}
     */
    @GetMapping("/get/{id}")
    public ActionResult<FtbNoticeAnnouncementsDetailDto> get(@PathVariable("id") String id) {
        return ActionResult.success("成功", ftbNoticeAnnouncementsService.getInfo(id, "app"));
    }

    /**
     * 删除公告
     *
     * @param id 主键id，必传
     * @return {@link ActionResult}
     */
    @DeleteMapping("/delete/{id}")
    public ActionResult<Boolean> delete(@PathVariable("id") String id) {
        ftbNoticeAnnouncementsService.deleteData(id);
        return ActionResult.success("删除成功", true);
    }


    /**
     * 发布接口
     *
     * @param id 公告主键ID，必传
     * @return {@link ActionResult}
     */
    @PostMapping("/publish/{id}")
    public ActionResult<Boolean> publish(@PathVariable("id") String id) {
        String lockKey = String.format(NoticeUtils.NOTICE_UPDATE_KEY, id);
        if (redisTemplate.opsForValue().setIfAbsent(lockKey, UUID.randomUUID().toString(), NoticeUtils.NOTICE_UPDATE_MAX_TIME, TimeUnit.SECONDS)) {
            try {
                ftbNoticeAnnouncementsService.publish(id);
                return ActionResult.success("发布成功", true);
            } catch (Exception e) {
                log.error("公告发布失败", e);
                return ActionResult.fail(e.getMessage());
            } finally {
                redisTemplate.delete(lockKey);
            }
        } else {
            throw new RuntimeException("提交中,请稍候");
        }
    }

    /**
     * 撤销接口
     *
     * @param id 公告主键ID，必传
     * @return {@link ActionResult}
     */
    @PostMapping("/cancelPublish/{id}")
    public ActionResult<Boolean> cancelPublish(@PathVariable("id") String id) {
        ftbNoticeAnnouncementsService.cancelPublish(id);
        return ActionResult.success("撤回成功", true);
    }

    /**
     * 根据公告ID提醒未读人员接口
     *
     * @param announcementId 公告ID
     * @return {@link ActionResult}
     */
    @PostMapping("/alertAll/{announcementId}")
    public ActionResult<Void> alertAll(@PathVariable("announcementId") String announcementId) {


        String lockKey = String.format(NoticeUtils.NOTICE_UPDATE_KEY, announcementId);
        if (redisTemplate.opsForValue().setIfAbsent(lockKey, UUID.randomUUID().toString(), NoticeUtils.NOTICE_UPDATE_MAX_TIME, TimeUnit.SECONDS)) {
            try {
                ftbNoticeAnnouncementsService.alertAll(announcementId);
                return ActionResult.success();
            } catch (Exception e) {
                log.error("公告发布失败", e);
                return ActionResult.fail(e.getMessage());
            } finally {
                redisTemplate.delete(lockKey);
            }
        } else {
            throw new RuntimeException("提交中,请稍候");
        }
    }

    /**
     * 提醒公告中一人未读接口
     *
     * @param announcementId 公告ID
     * @param userId         用户ID
     * @return {@link ActionResult}
     */
    @PostMapping("/alertOne/{announcementId}/{userId}")
    public ActionResult<Void> alertOne(@PathVariable("announcementId") String announcementId, @PathVariable("userId") String userId) {
        ftbNoticeAnnouncementsService.alertOne(announcementId, userId);
        return ActionResult.success();
    }


    /**
     * 查询公告中已读/未读人员列表
     *
     * @param req
     * @return {@link ActionResult}<{@link FtbNoticeAnnouncementsReceiveDto}>
     */
    @GetMapping("/queryUser")
    public ActionResult<PageListVO<FtbNoticeAnnouncementsReceiveDto>> queryUserList(@Validated QueryUserListReq req) {
        PageInfo<FtbNoticeAnnouncementsReceiveDto> pageVo = ftbNoticeAnnouncementsReceiveService.queryUserListForReadStatus(req, false);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }

}

