package com.usoftchina.uas.office.qywx.task;

import com.usoftchina.qywx.sdk.OaSdk;
import com.usoftchina.qywx.sdk.dto.GetCheckinDataReq;
import com.usoftchina.qywx.sdk.dto.GetCheckinDataResp;
import com.usoftchina.uas.office.entity.DataCenter;
import com.usoftchina.uas.office.jdbc.DataSourceHolder;
import com.usoftchina.uas.office.qywx.entity.CardLog;
import com.usoftchina.uas.office.qywx.entity.Employee;
import com.usoftchina.uas.office.qywx.entity.OutSign;
import com.usoftchina.uas.office.qywx.manage.service.QywxSettingService;
import com.usoftchina.uas.office.qywx.service.UasCardLogService;
import com.usoftchina.uas.office.qywx.service.UasEmployeeService;
import com.usoftchina.uas.office.qywx.service.UasOutSignService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author yingp
 * @date 2020/2/16
 */
@Component
public class QywxCheckinTask {

    @Autowired
    private OaSdk oaSdk;

    @Autowired
    private UasEmployeeService employeeService;

    @Autowired
    private QywxSettingService settingService;

    @Autowired
    private UasCardLogService cardLogService;

    @Autowired
    private UasOutSignService outSignService;

    /**
     * 每次最多条数据
     */
    private final int maxSeed = 100;

    private final Logger logger = LoggerFactory.getLogger(QywxCheckinTask.class);

    /**
     * 抓取打卡数据
     */
    @Scheduled(fixedDelay = 300000, initialDelay = 30000)
    public void pullCheckinData() {
        if (!oaSdk.isAgentEnabled(OaSdk.CHECKIN_AGENT_CODE)) {
            return;
        }
        DataCenter dataCenter = DataCenter.INSTANCE;
        if (null != dataCenter.getUsername() && null != dataCenter.getPassword() && null != dataCenter.getUrl()) {
            try {
                DataSourceHolder.set(dataCenter);
                List<Employee> employees = employeeService.getAll();
                if (!CollectionUtils.isEmpty(employees)) {
                    Map<String, Employee> employeeMap = employees.stream().collect(Collectors.toMap(Employee::getEm_qywx, e -> e));
                    Long lastTime = settingService.getCheckinTime();
                    if (lastTime == null) {
                        lastTime = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
                    }
                    Date now = new Date();
                    long unixStartTime = lastTime / 1000 + 1;
                    long unixEndTime = now.getTime() / 1000;
                    Stream.iterate(0, n -> n + 1)
                            .limit((int) Math.ceil((double) employees.size() / maxSeed)).forEach(page -> {
                        GetCheckinDataReq req = new GetCheckinDataReq(GetCheckinDataReq.CheckinType.ALL,
                                unixStartTime, unixEndTime,
                                employees.stream().skip(page * maxSeed).limit(maxSeed).map(Employee::getEm_qywx).collect(Collectors.toList()));
                        List<GetCheckinDataResp.CheckinData> dataList = oaSdk.getCheckinData(req);
                        saveCheckinData(employeeMap, dataList);
                    });
                    settingService.setCheckinTime(now);
                }
            } finally {
                DataSourceHolder.clear();
            }
        }
    }

    private void saveCheckinData(Map<String, Employee> employeeMap, List<GetCheckinDataResp.CheckinData> dataList) {
        dataList.forEach(data -> {
            Employee employee = employeeMap.get(data.getUserid());
            logger.debug("get checkin data, user {}, type {}", employee.getEm_name(), data.getCheckin_type());
            if ("外出打卡".equals(data.getCheckin_type())) {
                // 外勤签到 插入外勤打卡记录
                outSignService.save(new OutSign(employee, data));
            } else {
                cardLogService.save(new CardLog(employee, data));
            }
        });
    }
}
