package jnpf.workflow.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jnpf.attendance.antifreeze.UserAntifreeze;
import jnpf.attendance.service.AttendanceClockInPicService;
import jnpf.attendance.service.AttendanceClockInService;
import jnpf.attendance.service.handle.notice.AttendanceNoticeHandler;
import jnpf.base.UserInfo;
import jnpf.base.service.SuperServiceImpl;
import jnpf.constants.AttendanceConstant;
import jnpf.engine.vo.ApproverByTaskIdAndNodeIdVo;
import jnpf.entity.attendance.AttendanceClockInPic;
import jnpf.entity.workflow.ApplyAttendanceOutside;
import jnpf.enums.attendance.ApprovalSettingTypeEnum;
import jnpf.enums.attendance.AttendanceNoticeEnum;
import jnpf.model.attendance.vo.attendance.ApproveBaseImVo;
import jnpf.model.attendance.vo.attendance.ApproveImVo;
import jnpf.model.attendance.vo.attendance.AttendanceApproveImVo;
import jnpf.model.workflow.dto.ApplyAttendanceOutsideDto;
import jnpf.model.workflow.vo.ApplyAttendanceOutsideVo;
import jnpf.permission.model.user.PartUserInfoVo;
import jnpf.util.*;
import jnpf.workflow.mapper.ApplyAttendanceOutsideMapper;
import jnpf.workflow.service.ApplyAttendanceOutsideService;
import jnpf.workflow.service.ApplyPicService;
import jnpf.workflow.service.FlowTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 外勤审批服务实现
 *
 * @author yanwenfu
 * @create 2023-12-13
 */
@Slf4j
@Service
public class ApplyAttendanceOutsideServiceImpl extends SuperServiceImpl<ApplyAttendanceOutsideMapper, ApplyAttendanceOutside> implements ApplyAttendanceOutsideService {

    @Resource
    private FlowTaskService flowTaskService;
    @Autowired
    private UserAntifreeze userAntifreeze;
    @Autowired
    private UserProvider userProvider;
    @Autowired
    private AttendanceNoticeHandler attendanceNoticeHandler;
    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private CustomTenantUtil customTenantUtil;
    @Resource
    private AttendanceClockInService attendanceClockInService;
    @Resource
    private ApplyPicService applyPicService;

    @Override
    public ApplyAttendanceOutsideVo getApplyAttendanceOutside(String id) {

        ApplyAttendanceOutside applyAttendanceOutside = this.getById(id);
        return JsonUtil.getJsonToBean(applyAttendanceOutside, ApplyAttendanceOutsideVo.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(ApplyAttendanceOutside entity, ApplyAttendanceOutsideDto applyAttendanceOutsideDto) throws Exception {
        log.error("发起外勤审批: {}", applyAttendanceOutsideDto.toString());
        //保存外勤打卡图片 picUrlList
        List<String> urlList = applyPicService.getPicList(applyAttendanceOutsideDto.getPicUrlList());
        if (!urlList.isEmpty()) {
            applyAttendanceOutsideDto.getPicUrlList().clear();
            applyAttendanceOutsideDto.getPicUrlList().addAll(urlList);
        }
        applyPicService.saveClockPic(applyAttendanceOutsideDto.getTaskId(), applyAttendanceOutsideDto.getPicUrlList());
        UserInfo userInfo = userProvider.get();
        entity.setApplyUser(userInfo.getUserId());
        entity.setApplyDate(DateDetail.getStr2DateTime(applyAttendanceOutsideDto.getApplyDateStr()));
        entity.setTenantId(userInfo.getTenantId());
        entity.setId(applyAttendanceOutsideDto.getTaskId());
        entity.setRemark(applyAttendanceOutsideDto.getRemark());
        save(entity);
        attendanceClockInService.outsideClockIn(applyAttendanceOutsideDto.getTaskId(), userInfo.getUserId(), applyAttendanceOutsideDto.getClockInId());
    }

    private void sendToIm(ApplyAttendanceOutside entity, String tenantId) {

        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.schedule(() -> {
            customTenantUtil.checkOutTenant(tenantId);
            ApproverByTaskIdAndNodeIdVo data = flowTaskService.getApproveInfo(entity.getId(), null, tenantId, null);
            if (null == data) {
                return;
            }
            AttendanceApproveImVo approveIm = JsonUtil.getJsonToBean(data, AttendanceApproveImVo.class);
            approveIm.setId(data.getTaskId());
            List<PartUserInfoVo> userList = userAntifreeze.getAllByIds(List.of(entity.getApplyUserId()), tenantId);
            PartUserInfoVo userInfo = userList.stream().findFirst().orElse(null);
            // 组装消息
            ApproveImVo approveImVo = new ApproveImVo(tenantId, AttendanceNoticeEnum.APPROVE);
            String content = "%s的【外勤】审批";
            String title = String.format(content, null != userInfo ? userInfo.getRealName() : "--");
            ApproveBaseImVo imDetail = new ApproveBaseImVo(title, ApprovalSettingTypeEnum.OUT.getCode(), entity.getCreatorTime(), entity.getAddress());
            data.getUserOperators().forEach(v -> {
                approveIm.setTaskId(v.getTaskOperatorId());
                approveImVo.setUserIds(List.of(v.getUserId()));
                String encode = FtbUtil.encodeJson(approveIm);
                String url = AttendanceConstant.APPROVE_URL + encode;
                imDetail.setUrl(url);
                approveImVo.setApproveBaseImVo(imDetail);
                attendanceNoticeHandler.send(approveImVo);
                redisUtil.insert(ConstantUtil.APPROVE_NOTICE_OUTSIDE + approveIm.getId(), JSONUtil.toJsonStr(approveImVo));
            });
        }, 1, TimeUnit.SECONDS);
        scheduler.shutdown();
    }

    @Override
    public void submit(ApplyAttendanceOutside entity, ApplyAttendanceOutsideDto applyAttendanceOutsideDto) {
        //保存外勤打卡图片
        applyPicService.saveClockPic(applyAttendanceOutsideDto.getTaskId(), applyAttendanceOutsideDto.getPicUrlList());
        //表单信息
        if (StringUtil.isEmpty(entity.getId())) {
            entity.setId(applyAttendanceOutsideDto.getTaskId());
            save(entity);
            //sendToIm(entity, userProvider.get().getTenantId());
        } else {
            entity.setId(applyAttendanceOutsideDto.getTaskId());
            updateById(entity);
        }
    }
}
