package jnpf.attendance.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jnpf.attendance.antifreeze.UserAntifreeze;
import jnpf.attendance.mapper.AttendanceNoticeMapper;
import jnpf.attendance.service.AttendanceNoticeService;
import jnpf.base.UserInfo;
import jnpf.constants.AttendanceConstant;
import jnpf.entity.attendance.AttendanceNoticeEntity;
import jnpf.enums.attendance.AttendanceNoticeEnum;
import jnpf.model.attendance.dto.NoticeContentInfoDto;
import jnpf.model.attendance.dto.NoticeSaveDto;
import jnpf.model.attendance.model.NoticeConfirm;
import jnpf.model.attendance.vo.NoticeConfirmListVo;
import jnpf.model.attendance.vo.NoticeConfirmVo;
import jnpf.model.attendance.vo.NoticeContentInfoVo;
import jnpf.permission.model.user.PartUserInfoVo;
import jnpf.util.UploaderUtil;
import jnpf.util.UserProvider;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.alibaba.fastjson.JSON.parseArray;

/**
 * 考勤消息通知
 *
 * @author shitou
 * @email shitou@niujiekeji.com
 * @date 2024-08-08 10:49:41
 */
@Service
public class AttendanceNoticeServiceImpl extends ServiceImpl<AttendanceNoticeMapper, AttendanceNoticeEntity> implements AttendanceNoticeService {

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private UserAntifreeze userAntifreeze;

    @Override
    public NoticeContentInfoVo getContentInfo(NoticeContentInfoDto req) {
        AttendanceNoticeEntity attendanceNotice = this.getById(req.getId());
        Assert.notNull(attendanceNotice, "未查询到消息通知");
        AttendanceNoticeEnum noticeEnum = AttendanceNoticeEnum.getAttendanceNoticeEnum(attendanceNotice.getType());
        Assert.notNull(noticeEnum, "未查询到相应的消息通知类型");
        List<JSONObject> shiftsJsonVoList = parseArray(attendanceNotice.getDataJson(), JSONObject.class);
        NoticeContentInfoVo contentInfoVo = new NoticeContentInfoVo();
        if (Objects.nonNull(attendanceNotice.getCreatorUserId())) {
            List<PartUserInfoVo> allByIds = userAntifreeze.getAllByIds(CollUtil.newArrayList(attendanceNotice.getCreatorUserId()), UserProvider.getUser().getTenantId());
            PartUserInfoVo partUserInfoVo = allByIds.stream().findFirst().orElse(null);
            if (Objects.nonNull(partUserInfoVo)) {
                String operator = partUserInfoVo.getRealName() + "(" + partUserInfoVo.getOrganizeName() + "-" + partUserInfoVo.getPositionName() + ")";
                contentInfoVo.setOperator(operator);
            }
        }
        contentInfoVo.setTitle(attendanceNotice.getTitle());
        contentInfoVo.setTime(attendanceNotice.getCreatorTime());
        contentInfoVo.setDataList(shiftsJsonVoList);
        return contentInfoVo;
    }

    @Override
    public void noticeSave(NoticeSaveDto noticeSaveDto) {
        this.save(AttendanceNoticeEntity.builder()
                .id(noticeSaveDto.getId())
                .type(noticeSaveDto.getType().getCode())
                .title(StringUtils.isNotEmpty(noticeSaveDto.getTitle()) ? noticeSaveDto.getTitle() : null)
                .dataJson(StringUtils.isNotEmpty(noticeSaveDto.getDataJson()) ? noticeSaveDto.getDataJson() : null)
                .isConfirm(Objects.nonNull(noticeSaveDto.getIsConfirm()) ? noticeSaveDto.getIsConfirm() : null)
                .confirmList(StringUtils.isNotEmpty(noticeSaveDto.getConfirmList()) ? noticeSaveDto.getConfirmList() : null)
                .creatorTime(new Date())
                .creatorUserId(StringUtils.isNotEmpty(noticeSaveDto.getUserId()) ? noticeSaveDto.getUserId() : null)
                .build());
    }

    @Override
    public void noticeConfirm(String id) {
        UserInfo user = UserProvider.getUser();
        String key = String.format(AttendanceConstant.FTB_ATTENDANCE_NOTICE_CONFIRM_KEY, user.getTenantId(), id);
        RLock lock = redissonClient.getLock(key);
        try {
            if (lock.tryLock(10,20,  TimeUnit.SECONDS)) {
                AttendanceNoticeEntity byId = getById(id);
                if (Objects.equals(byId.getIsConfirm(), 0) || StringUtils.isEmpty(byId.getConfirmList())) {
                    log.error("当前通知未开启确认功能");
                    return;
                }
                List<NoticeConfirm> noticeConfirms = JSONObject.parseArray(byId.getConfirmList(), NoticeConfirm.class);
                if (CollUtil.isEmpty(noticeConfirms)) {
                    log.error("当前通知未获取到确认列表");
                    return;
                }
                noticeConfirms.stream().filter(noticeConfirm -> StringUtils.equals(noticeConfirm.getUserId(), user.getUserId())).forEach(noticeConfirm -> {
                    noticeConfirm.setIsConfirmed(1);
                    noticeConfirm.setConfirmedTime(new Date());
                });
                byId.setConfirmList(JSON.toJSONString(noticeConfirms));
                updateById(byId);

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    @Override
    public NoticeConfirmListVo getNoticeConfirmList(String id) {
        AttendanceNoticeEntity byId = getById(id);
        Assert.isFalse(Objects.equals(byId.getIsConfirm(), 0) || StringUtils.isEmpty(byId.getConfirmList()), "当前通知未开启确认功能");
        List<NoticeConfirm> noticeConfirms = JSONObject.parseArray(byId.getConfirmList(), NoticeConfirm.class);
        if (CollUtil.isEmpty(noticeConfirms)) {
            return NoticeConfirmListVo.builder().build();
        }
        List<String> userIds = noticeConfirms.stream().map(NoticeConfirm::getUserId).collect(Collectors.toList());
        List<PartUserInfoVo> allByIds = userAntifreeze.getAllByIds(userIds, UserProvider.getUser().getTenantId());
        Map<String, PartUserInfoVo> collect = allByIds.stream().collect(Collectors.toMap(PartUserInfoVo::getUserId, Function.identity()));
        List<NoticeConfirmVo> collect1 = noticeConfirms.stream().map(noticeConfirm -> {
            PartUserInfoVo partUserInfoVo = collect.get(noticeConfirm.getUserId());
            return NoticeConfirmVo.builder()
                    .userId(noticeConfirm.getUserId())
                    .userName(partUserInfoVo.getRealName())
                    .head(UploaderUtil.uploaderImg(partUserInfoVo.getHeadIcon()))
                    .org(partUserInfoVo.getOrganizeName())
                    .position(partUserInfoVo.getPositionName())
                    .isConfirmed(noticeConfirm.getIsConfirmed())
                    .confirmedTime(noticeConfirm.getConfirmedTime())
                    .build();
        }).collect(Collectors.toList());
        List<NoticeConfirmVo> collect2 = collect1.stream().filter(noticeConfirmVo -> Objects.equals(noticeConfirmVo.getIsConfirmed(), 1)).collect(Collectors.toList());
        List<NoticeConfirmVo> collect3 = collect1.stream().filter(noticeConfirmVo -> Objects.equals(noticeConfirmVo.getIsConfirmed(), 0)).collect(Collectors.toList());
        return NoticeConfirmListVo.builder().confirmedList(collect2).notConfirmList(collect3).build();
    }
}
