package com.malk.service.fxiaoke.impl;

import cn.hutool.core.util.ObjectUtil;
import com.malk.server.fxiaoke.FXKConf;
import com.malk.server.fxiaoke.FXXR;
import com.malk.service.fxiaoke.FXKClient;
import com.malk.utils.UtilMap;
import com.malk.utils.UtilToken;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class FXKImplClient implements FXKClient {

    @Autowired
    private FXKConf fxkConf;

    private final static String UNIQUE_STORAGE_ID = "invalid-token-fxiaoke";

    /**
     * 获取访问授权
     *
     * @apiNote https://open.fxiaoke.com/wiki.html#artiId=17
     */
    @Synchronized
    @Override
    public String getAccessToken() {
        String accessToken = UtilToken.get(UNIQUE_STORAGE_ID);
        if (StringUtils.isNotBlank(accessToken)) return accessToken;
        Map body = new HashMap();
        body.put("appId", fxkConf.getAppId());
        body.put("appSecret", fxkConf.getAppSecret());
        body.put("permanentCode", fxkConf.getPermanentCode());
        FXXR r = FXXR.doPost("https://open.fxiaoke.com/cgi/corpAccessToken/get/V2", null, null, body);
        log.info("响应token, {}", r.getCorpAccessToken());
        accessToken = r.getCorpAccessToken();
        // token失效自动重置: FXK重新调用不会重置过期时间
        UtilToken.put(UNIQUE_STORAGE_ID, accessToken, r.getExpiresIn() * 1000L);
        return accessToken;
    }

    /**
     * 根据手机号查询员工
     *
     * @apiNote https://open.fxiaoke.com/wiki.html#artiId=1122
     */
    @Override
    public List<Map> getUserByMobile(String accessToken, String corpId, String mobile) {
        Map body = UtilMap.map("corpAccessToken, corpId, mobile", accessToken, corpId, mobile);
        FXXR fxxr = FXXR.doPost("https://open.fxiaoke.com/cgi/user/getByMobile", null, null, body);
        return fxxr.getEmpList();
    }

    /**
     * 获取考勤数据列表 [考勤 - 打卡]
     *
     * @apiNote https://open.fxiaoke.com/wiki.html#artiId=153
     */
    @Override
    public List<Map> getAttendance(String accessToken, String corpId, long startTime, long endTime, List<String> openUserIds, Pageable pageable) {
        Map body = UtilMap.map("corpAccessToken, corpId, startTime, endTime, openUserIds", accessToken, corpId, startTime, endTime, openUserIds);
        if (ObjectUtil.isNull(pageable)) {
            body.put("pageSize", 1000);
            body.put("pageNumber", 1);
        }
        FXXR fxxr = FXXR.doPost("https://open.fxiaoke.com/cgi/attendance/find", null, null, body);
        return fxxr.getDatas();
    }


    /**
     * 获取考勤数据列表 [外勤 - 签到]
     *
     * @apiNote https://open.fxiaoke.com/wiki.html#artiId=153
     */
    @Override
    public List<Map> getAttendanceForOutside(String accessToken, String corpId, long startTime, long endTime, List<String> openUserIds, Pageable pageable) {
        Map body = UtilMap.map("corpAccessToken, corpId, startTime, endTime, openUserIds", accessToken, corpId, startTime, endTime, openUserIds);
        if (ObjectUtil.isNull(pageable)) {
            body.put("pageSize", 1000);
            body.put("pageNumber", 1);
        }
        FXXR fxxr = FXXR.doPost("https://open.fxiaoke.com/cgi/outsideAttendance/find", null, null, body);
        return fxxr.getDatas();
    }

    /**
     * 获取考勤_全部 [最大分页]
     */
    @Override
    public List<Map> getAttendance_All(String accessToken, String corpId, long startTime, long endTime, List<String> openUserIds) {
        List<Map> attendanceList = getAttendance(accessToken, corpId, startTime, endTime, openUserIds, null);
        attendanceList.addAll(getAttendanceForOutside(accessToken, corpId, startTime, endTime, openUserIds, null).stream().map(item -> {
            // 字段合并
            item.put("checkTime", item.get("checkinsTimeStamp"));
            item.put("checkAddress", item.get("checkinsAddressDesc"));
            item.put("outside", "外勤");
            return item;
        }).collect(Collectors.toList()));
        return attendanceList;
    }
}
