package cn.com.qmth.examcloud.tool.service.batch_create_user;

import cn.com.qmth.examcloud.tool.cache.LoginSessionManager;
import cn.com.qmth.examcloud.tool.config.SysProperty;
import cn.com.qmth.examcloud.tool.entity.TaskEntity;
import cn.com.qmth.examcloud.tool.service.CommonService;
import cn.com.qmth.examcloud.tool.service.TaskService;
import cn.com.qmth.examcloud.tool.service.batch_create_user.vo.UserInfo;
import cn.com.qmth.examcloud.tool.service.batch_create_user.vo.UserInfoListener;
import cn.com.qmth.examcloud.tool.utils.HttpHelper;
import cn.com.qmth.examcloud.tool.utils.JsonMapper;
import cn.com.qmth.examcloud.tool.utils.StatusException;
import cn.com.qmth.examcloud.tool.vo.user.User;
import com.alibaba.excel.EasyExcel;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class BatchCreateUserTask implements TaskService {

    private final static Logger log = LoggerFactory.getLogger(BatchCreateUserTask.class);

    @Autowired
    private SysProperty sysProperty;

    @Autowired
    private CommonService commonService;

    @Override
    public void start(TaskEntity task) {
        User loginUser = LoginSessionManager.getLoginSession(task.getUserToken());
        if (loginUser == null) {
            throw new StatusException("用户未登录！");
        }

        this.execute(loginUser, task);
    }

    private void execute(User loginUser, TaskEntity task) {
        JsonNode jsonParams = new JsonMapper().getNode(task.getParams());
        if (jsonParams == null) {
            throw new StatusException("任务参数解析错误！");
        }

        String dataFilePath = jsonParams.get("dataFilePath").asText();
        if (StringUtils.isBlank(dataFilePath)) {
            throw new StatusException("参数dataFilePath不能为空！");
        }

        UserInfoListener dataListener = new UserInfoListener();
        EasyExcel.read(dataFilePath, UserInfo.class, dataListener).sheet().doRead();
        List<UserInfo> dataList = dataListener.getList();

        int total = dataList.size();
        log.info("共{}条数据！", total);

        // 检验数据
        Map<String, Long> orgMaps = new HashMap<>();
        Map<String, Long> courseMaps = new HashMap<>();
        Map<String, Long> roleMaps = commonService.queryRoles(loginUser);

        List<String> errMessages = new ArrayList<>();
        for (int i = 0; i < total; i++) {
            UserInfo user = dataList.get(i);

            if (StringUtils.isBlank(user.getLoginName())) {
                errMessages.add("第" + (i + 1) + "条 登录名不能为空！");
            } else {
                user.setLoginName(user.getLoginName().trim());
            }

            if (StringUtils.isBlank(user.getUserName())) {
                errMessages.add("第" + (i + 1) + "条 姓名不能为空！");
            } else {
                user.setUserName(user.getUserName().trim());
            }

            if (StringUtils.isBlank(user.getPsw())) {
                errMessages.add("第" + (i + 1) + "条 密码不能为空！");
            } else {
                user.setPsw(user.getPsw().trim());
            }

            Long roleId = roleMaps.get(user.getRoleName());
            if (roleId == null) {
                errMessages.add("第" + (i + 1) + "条 角色内容有误！");
            } else {
                user.setRoleId(roleId);
            }

            if (!this.isAll(user.getRefExam())) {
                user.setRefExamIds(this.parseLongValues(user.getRefExam()));
            }

            if (!this.isAll(user.getRefOrg())) {
                List<String> codes = this.parseValues(user.getRefOrg());
                List<Long> refOrgIds = new ArrayList<>();

                for (String code : codes) {
                    Long orgId = orgMaps.get(code);
                    if (orgId == null) {
                        orgId = commonService.queryOrgIdByCode(loginUser, code);
                        if (orgId == null) {
                            errMessages.add("第" + (i + 1) + "条 机构代码不正确！" + code);
                        } else {
                            orgMaps.put(code, orgId);
                            refOrgIds.add(orgId);
                        }
                    } else {
                        refOrgIds.add(orgId);
                    }
                }
                user.setRefOrgIds(refOrgIds);
            }

            if (!this.isAll(user.getRefCourse())) {
                List<String> codes = this.parseValues(user.getRefCourse());
                List<Long> refCourseIds = new ArrayList<>();

                for (String code : codes) {
                    Long courseId = courseMaps.get(code);
                    if (courseId == null) {
                        courseId = commonService.queryCourseIdByCode(loginUser, code);
                        if (courseId == null) {
                            errMessages.add("第" + (i + 1) + "条 课程代码不正确！" + code);
                        } else {
                            courseMaps.put(code, courseId);
                            refCourseIds.add(courseId);
                        }
                    } else {
                        refCourseIds.add(courseId);
                    }
                }
                user.setRefCourseIds(refCourseIds);
            }
        }

        if (!errMessages.isEmpty()) {
            throw new StatusException(StringUtils.join(errMessages, "\n"));
        }

        int failCount = 0;
        for (int i = 0; i < total; i++) {
            UserInfo user = dataList.get(i);
            this.createUser(loginUser, user);

            UserInfo existUser = commonService.queryUserByLoginName(loginUser, user.getLoginName());
            if (existUser == null) {
                log.warn("共{}条 第{}条 用户创建失败！{}", total, i + 1, user.getLoginName());
                failCount++;
                continue;
            }

            user.setId(existUser.getId());
            this.updateDataRuleForExam(loginUser, user);
            this.updateDataRuleForCourse(loginUser, user);
            this.updateDataRuleForOrg(loginUser, user);

            log.info("共{}条 第{}条 已执行！{}", total, i + 1, user.getLoginName());
        }

        String msg = String.format("共%s条 成功%s条 失败%s条！", total, total - failCount, failCount);
        log.info(msg);
        task.setDescription(msg);
    }

    private void createUser(User loginUser, UserInfo user) {
        Map<String, String> headers = new HashMap<>();
        headers.put("key", loginUser.getKey());
        headers.put("token", loginUser.getToken());

        Map<String, Object> params = new HashMap<>();
        params.put("rootOrgId", loginUser.getRootOrgId());
        params.put("name", user.getUserName());
        params.put("loginName", user.getLoginName());
        params.put("password", user.getPsw());
        params.put("phoneNumber", user.getPhoneNumber());
        params.put("enable", true);
        params.put("roleIds", new Long[]{user.getRoleId()});
        if (CollectionUtils.isNotEmpty(user.getRefOrgIds())) {
            params.put("orgId", user.getRefOrgIds().get(0));
        }

        try {
            String url = loginUser.getServerUrl() + "/api/ecs_core/user";
            String result = HttpHelper.post(url, headers, params);
            log.info(result);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    private void updateDataRuleForExam(User loginUser, UserInfo user) {
        Map<String, String> headers = new HashMap<>();
        headers.put("key", loginUser.getKey());
        headers.put("token", loginUser.getToken());

        if (this.isAll(user.getRefExam())) {
            String url = loginUser.getServerUrl() + "/api/ecs_core/user/data/rule/default/status/update?type=EXAM&enabled=true&userId=" + user.getId();
            HttpHelper.post(url, headers, null);
        } else {
            if (CollectionUtils.isEmpty(user.getRefExamIds())) {
                return;
            }

            String url = loginUser.getServerUrl() + "/api/ecs_core/user/data/rule/add";
            Map<String, Object> params = new HashMap<>();
            params.put("type", "EXAM");
            params.put("userId", user.getId());
            params.put("refIds", user.getRefExamIds());
            HttpHelper.post(url, headers, params);
        }
    }

    private void updateDataRuleForCourse(User loginUser, UserInfo user) {
        Map<String, String> headers = new HashMap<>();
        headers.put("key", loginUser.getKey());
        headers.put("token", loginUser.getToken());

        if (this.isAll(user.getRefCourse())) {
            String url = loginUser.getServerUrl() + "/api/ecs_core/user/data/rule/default/status/update?type=COURSE&enabled=true&userId=" + user.getId();
            HttpHelper.post(url, headers, null);
        } else {
            if (CollectionUtils.isEmpty(user.getRefCourseIds())) {
                return;
            }

            String url = loginUser.getServerUrl() + "/api/ecs_core/user/data/rule/add";
            Map<String, Object> params = new HashMap<>();
            params.put("type", "COURSE");
            params.put("userId", user.getId());
            params.put("refIds", user.getRefCourseIds());
            HttpHelper.post(url, headers, params);
        }
    }

    private void updateDataRuleForOrg(User loginUser, UserInfo user) {
        Map<String, String> headers = new HashMap<>();
        headers.put("key", loginUser.getKey());
        headers.put("token", loginUser.getToken());

        if (this.isAll(user.getRefOrg())) {
            String url = loginUser.getServerUrl() + "/api/ecs_core/user/data/rule/default/status/update?type=ORG&enabled=true&userId=" + user.getId();
            HttpHelper.post(url, headers, null);
        } else {
            if (CollectionUtils.isEmpty(user.getRefOrgIds())) {
                return;
            }

            String url = loginUser.getServerUrl() + "/api/ecs_core/user/data/rule/add";
            Map<String, Object> params = new HashMap<>();
            params.put("type", "ORG");
            params.put("userId", user.getId());
            params.put("refIds", user.getRefOrgIds());
            HttpHelper.post(url, headers, params);
        }
    }

    private List<Long> parseLongValues(String str) {
        if (StringUtils.isBlank(str)) {
            return new ArrayList<>();
        }

        List<Long> values = new ArrayList<>();
        String[] vv = str.split(",");
        for (String v : vv) {
            v = v.trim();
            if (!StringUtils.isNumeric(v)) {
                continue;
            }
            values.add(Long.valueOf(v));
        }

        return values;
    }

    private List<String> parseValues(String str) {
        if (StringUtils.isBlank(str)) {
            return new ArrayList<>();
        }

        List<String> values = new ArrayList<>();
        String[] vv = str.split(",");
        for (String v : vv) {
            v = v.trim();
            if (StringUtils.isEmpty(v)) {
                continue;
            }
            values.add(v);
        }

        return values;
    }

    private boolean isAll(String str) {
        return "全部".equals(str);
    }

}
