package com.foc.hrm.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.foc.conf.Constants;
import com.foc.conf.GConstants;
import com.foc.hrm.entity.UserEmpPostEntity;
import com.foc.hrm.entity.UserEntity;
import com.foc.ods.entity.OdsChangesEntity;
import com.foc.office.entity.OfficeEntity;
import com.foc.office.service.OfficeService;
import com.foc.util.*;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.lang3.StringUtils;

import java.sql.SQLException;
import java.util.*;

/**
 * @author lisu
 */
public class HRMService {

    QueryRunner run = null;

    public static final int HASH_INTERATIONS = 1024;
    public static final int SALT_SIZE = 8;

    private OfficeService officeService;

    public HRMService() {
        try {
            this.run = new QueryRunner(DBHelper.getDataSource());
            officeService = new OfficeService(this.run);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void insertHRM(JSONObject result, final String modified) {

        JSONObject dataJson = (JSONObject) result.get("data");
        JSONArray jsonArray = (JSONArray) dataJson.get("apiResp");

        if (jsonArray != null && jsonArray.size() > 0) {
            int index = 0;
            int size = jsonArray.size();
            for (int i = 0; i < size; i++) {
                index++;
                try {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    String username = (String) jsonObject.get("name");
                    String userId = (String) jsonObject.get("employeeId");
                    String account = (String) jsonObject.get("account");
                    String deptFullname = (String) jsonObject.get("deptFullname");

                    System.out.println("【HRM】第【" + index + "/" + size + "】条【" + userId + "】【" + username + "】【" + account + "】【" + deptFullname + "】");
                    // 只导入有账号信息的用户
                    if (StringUtils.isBlank(userId) || StringUtils.isBlank(account) || StringUtils.isBlank(deptFullname)) {
                        System.out.println("【跳过】");
                        continue;
                    }

                    System.out.println("【正常】");
                    UserEntity user = checkUserExist(userId);
                    if (user != null) {
                        update(user, jsonObject, userId, modified);
                    } else {
                        insert(jsonObject, modified);
                    }

                    if (checkUserProfileExist(userId)) {
                        updateUserProfile(jsonObject);
                    } else {
                        insertUserProfile(jsonObject);
                    }
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
        }
    }

    private void insert(JSONObject jsonObject, final String modified) throws SQLException {

        String deptFullname = (String) jsonObject.get("deptFullname");

        if (StringUtils.isNotBlank(deptFullname)) {
            OfficeEntity office = this.officeService.addOffice(deptFullname);

            String fullName = deptFullname.replaceAll("[\\+|\\s+]", "");
            String[] species = fullName.split("-");
            OfficeEntity company = this.officeService.getOfficeByName(species[0], null);

            if (office == null || company == null) {
                return;
            }
            insertUser(jsonObject, company.getId(), office.getId(), modified);

            String userId = (String) jsonObject.get("employeeId");
            insertUser2RoleData(userId);
        }
    }

    private void insertUser2RoleData(String userId) {

        Map<MapType, UserEntity> userEntityMap = new HashMap<MapType, UserEntity>();
        if (checkUserExist(userEntityMap, userId)) {
            UserEntity userEntity = userEntityMap.get(MapType.userEntityType);
            if (!existUser2RoleWithUserId(userEntity.getId())) {
                insertUser2Role(userEntity.getId(), GConstants.getValue("innerRoleId"));
            }
        }
    }

    private boolean existUser2RoleWithUserId(String userId) {
        ResultSetHandler<List<OdsChangesEntity>> handler = new BeanListHandler<OdsChangesEntity>(
                OdsChangesEntity.class);
        String query = "SELECT * FROM " + Constants.SYS_USER2ROLE + " WHERE user_id ='" + userId + "'";
        List<OdsChangesEntity> list = null;
        try {
            list = run.query(query, handler);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (list != null && list.size() > 0) {
            return true;
        }

        return false;
    }

    private void insertUser2Role(String userId, String roleId) {

        if (StringUtils.isBlank(userId)) {
            throw new IllegalArgumentException("userId 不能为空");
        }

        if (StringUtils.isBlank(roleId)) {
            throw new IllegalArgumentException("roleId 不能为空");
        }

        List<Map<String, Object>> columnMapList = new ArrayList<Map<String, Object>>();

        Map<String, Object> columnMap = new TreeMap<String, Object>();
        // 字段和值绑定
        columnMap.put("user_id", userId);
        columnMap.put("role_id", roleId);

        columnMapList.add(columnMap);

        /**
         * 单条插入，保证一条语句插入报错，还能往下执行
         */
        DBHandler dBHandler = new DBHandler();
        dBHandler.batchInsert(Constants.SYS_USER2ROLE, columnMapList);
    }

    private boolean checkUserExist(Map<MapType, UserEntity> userEntityMap, String userId) {
        ResultSetHandler<List<UserEntity>> handler = new BeanListHandler<UserEntity>(UserEntity.class);
        String query = "SELECT * FROM " + Constants.SYS_USER + " WHERE id ='" + userId + "'";
        List<UserEntity> list = null;
        try {
            list = run.query(query, handler);
            if (list != null && list.size() > 0) {
                userEntityMap.put(MapType.userEntityType, list.get(0));
                return true;
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return false;
    }


    private void insertUser(JSONObject jsonObject, String companyId, String officeId, final String modified) throws SQLException {

        DBHandler dBHandler = new DBHandler();
        Map<String, Object> columnMap = new TreeMap<String, Object>();

        List<Map<String, Object>> columnMapList = new ArrayList<Map<String, Object>>();
        // 字段和值绑定
        columnMap.put("id", jsonObject.get("employeeId"));
        columnMap.put("no", jsonObject.get("employeeId"));
        columnMap.put("full_office_name", jsonObject.get("deptFullname"));
        columnMap.put("name", jsonObject.get("name"));
        columnMap.put("mobile", jsonObject.get("mobile"));

        String workPhone = jsonObject.getString("workPhone");
        columnMap.put("phone", getWorkPhone(workPhone));
        columnMap.put("phone_number", Util.formatedWorkPhone(workPhone));
        columnMap.put("email", jsonObject.get("email"));

        columnMap.put("update_date", jsonObject.get("operatorDate"));

        columnMap.put("office_id", officeId);

        columnMap.put("company_id", companyId);
        columnMap.put("login_name", jsonObject.get("account"));

        columnMap.put("password", "");
        columnMap.put("create_by", "1");
        columnMap.put("create_date", DateUtil.dateToStr(new Date(), DateUtil.TIMEF_FORMAT));
        columnMap.put("update_by", "1");
        columnMap.put("del_flag", "0");
        columnMap.put("user_type", "2");
        columnMap.put("photo", this.getPhoto(jsonObject.getString("sex")));
        columnMapList.add(columnMap);

        dBHandler.batchInsert(Constants.SYS_USER, columnMapList);
    }

    public String getPhoto(String sex) {
        // 1：男，0：女
        if ("0".equals(sex) || "F".equalsIgnoreCase(sex)) {
            // F：女
            return GConstants.getValue("female.photo");
        }
        return GConstants.getValue("male.photo");
    }

    private Map<String, Object> getUserProfile(JSONObject jsonObject) {
        Map<String, Object> columnMap = new TreeMap<String, Object>();
        columnMap.put("user_id", jsonObject.get("employeeId"));
        columnMap.put("fax", jsonObject.get("fax"));
        String sex = jsonObject.getString("sex");
        // 1：男，0：女
        if ("0".equals(sex) || "F".equalsIgnoreCase(sex)) {
            // F：女
            columnMap.put("sex", "F");
        } else {
            // M：男
            columnMap.put("sex", "M");
        }
        columnMap.put("duty_name", "");
        if (jsonObject.containsKey("empPosts")) {
            JSONArray empPosts = jsonObject.getJSONArray("empPosts");
            if (empPosts != null && empPosts.size() > 0) {
                UserEmpPostEntity lastEmpPost = null;
                List<UserEmpPostEntity> empPostList = JSON.parseArray(empPosts.toJSONString(), UserEmpPostEntity.class);
                if (empPostList != null && empPostList.size() > 0) {
                    for (UserEmpPostEntity userEmpPost : empPostList) {
                        try {
                            if (lastEmpPost == null
                                    || lastEmpPost.getUpdatedTime().getTime() < userEmpPost.getUpdatedTime().getTime()) {
                                lastEmpPost = userEmpPost;
                            }
                        } catch (Exception e) {
                            // TODO: handle exception
                        }
                    }
                }
                if (lastEmpPost != null && StringUtils.isNotEmpty(lastEmpPost.getPostName())) {

                    columnMap.put("duty_name", lastEmpPost.getPostName());
                }
            }
        }
        return columnMap;
    }

    private void insertUserProfile(JSONObject jsonObject) throws SQLException {

        DBHandler dBHandler = new DBHandler();
        Map<String, Object> columnMap = this.getUserProfile(jsonObject);

        List<Map<String, Object>> columnMapList = new ArrayList<Map<String, Object>>();
        columnMapList.add(columnMap);

        dBHandler.batchInsert(Constants.SYS_USER_PROFILES, columnMapList);
    }

    private void updateUserProfile(JSONObject jsonObject) throws SQLException {

        DBHandler dBHandler = new DBHandler();
        Map<String, Object> columnMap = this.getUserProfile(jsonObject);

        Map<String, Object> whereMap = new TreeMap<String, Object>();
        whereMap.put("user_id", jsonObject.get("employeeId"));

        dBHandler.update(Constants.SYS_USER_PROFILES, columnMap, whereMap);
    }

    /**
     * @param deptName
     * @param parentId
     * @param parentIds
     * @throws SQLException
     */
    public void insertOfficeByRecursive(Map<MapType, OfficeEntity> resultOfficeEntityMap, String deptName,
                                        String parentId, String parentIds) throws SQLException {

        if (StringUtils.isBlank(deptName)) {
            return;
        }

        String firstDeptName = null;
        String subDeptName = null;
        if (deptName.indexOf("-") > 0) {
            firstDeptName = deptName.substring(0, deptName.indexOf("-"));
            subDeptName = deptName.substring(deptName.indexOf("-") + 1);
        } else {
            firstDeptName = deptName;
        }

        Map<MapType, OfficeEntity> existOfficeEntityMap = new HashMap<MapType, OfficeEntity>();
        OfficeEntity existOfficeEntity = null;
        if (checkOfficeExist(existOfficeEntityMap, firstDeptName, parentId)) {
            existOfficeEntity = existOfficeEntityMap.get(MapType.existOfficeEntityType);
            if (isOfficeExistLastDept(firstDeptName, subDeptName)) {
                setResultOfficeEntityMap(resultOfficeEntityMap, existOfficeEntity);
                return;
            }

            insertOfficeByRecursive(resultOfficeEntityMap, subDeptName, existOfficeEntity.getId(),
                    existOfficeEntity.getParentIds() + "," + existOfficeEntity.getId());
        } else {
            insertOffice(firstDeptName, parentId, parentIds);
            OfficeEntity insertedOfficeEntity = findOfficeByDeptNameAndParentId(firstDeptName, parentId);
            if (isLastDept(subDeptName)) {
                setResultOfficeEntityMap(resultOfficeEntityMap, insertedOfficeEntity);
                return;
            }
            insertOfficeByRecursive(resultOfficeEntityMap, subDeptName, insertedOfficeEntity.getId(),
                    insertedOfficeEntity.getParentIds() + "," + insertedOfficeEntity.getId());
        }
    }

    private boolean isOfficeExistLastDept(String firstDeptName, String subDeptName) {

        if (StringUtils.isNotBlank(firstDeptName) && StringUtils.isBlank(subDeptName)) {
            return true;
        }
        return false;
    }

    private void setResultOfficeEntityMap(Map<MapType, OfficeEntity> resultOfficeEntityMap, OfficeEntity officeEntity) {
        if (officeEntity == null) {
        }
        resultOfficeEntityMap.put(MapType.resultOfficeEntityType, officeEntity);
    }

    private boolean isLastDept(String subDeptName) {
        if (subDeptName == null)
            return true;
        return false;
    }

    private void insertOffice(String firstDeptName, String parentId, String parentIds) {

        List<Map<String, Object>> columnMapList = new ArrayList<Map<String, Object>>();

        Map<String, Object> columnMap = new TreeMap<String, Object>();
        // 字段和值绑定
        columnMap.put("name", firstDeptName);
        columnMap.put("id", IdWorker.getNextId());
        if (parentId == null) {
            columnMap.put("parent_id", "0");
            columnMap.put("parent_ids", "0,");
            columnMap.put("type", "1");
        } else {
            columnMap.put("parent_id", parentId);
            columnMap.put("parent_ids", parentIds + ",");
            columnMap.put("type", "2");
        }
        columnMap.put("area_id", GConstants.getValue("default.area.id", "1"));
        columnMap.put("USEABLE", "1");
        columnMap.put("sort", "30");
        columnMap.put("grade", "1");
        columnMap.put("create_by", "1");
        columnMap.put("create_date", DateUtil.dateToStr(new Date(), DateUtil.TIMEF_FORMAT));
        columnMap.put("update_by", "1");
        columnMap.put("update_date", DateUtil.dateToStr(new Date(), DateUtil.TIMEF_FORMAT));
        columnMap.put("del_flag", "0");

        columnMapList.add(columnMap);

        // 批量插入数据
        DBHandler dBHandler = new DBHandler();
        dBHandler.batchInsert(Constants.SYS_OFFICE, columnMapList);
    }

    private boolean checkOfficeExist(Map<MapType, OfficeEntity> officeEntityMap, String firstDeptName,
                                     String parentId) {

        OfficeEntity resultOfficeEntity = null;
        try {
            resultOfficeEntity = findOfficeByDeptNameAndParentId(firstDeptName, parentId);

            officeEntityMap.put(MapType.existOfficeEntityType, resultOfficeEntity);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (resultOfficeEntity != null)
            return true;
        return false;
    }

    private OfficeEntity findOfficeByDeptNameAndParentId(String firstDeptName, String parentId) throws SQLException {

        firstDeptName = firstDeptName.replaceAll("\\\\", "\\\\\\\\");

        ResultSetHandler<List<OfficeEntity>> handler = new BeanListHandler<OfficeEntity>(OfficeEntity.class);

        String query = "SELECT *, parent_id as parentId, parent_ids as parentIds FROM sys_office WHERE 1 = 1";
        if (parentId == null) {
            // 查询顶级部门
            parentId = "0";
        }
        query += " and parent_id ='" + parentId + "' and name = '" + firstDeptName + "'";
        List<OfficeEntity> list = this.run.query(query, handler);

        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    private void update(UserEntity lastUserInfo, JSONObject jsonObject, String userId, final String modified) throws SQLException {

        String deptFullname = (String) jsonObject.get("deptFullname");

        if (StringUtils.isNotBlank(deptFullname)) {
            OfficeEntity office = this.officeService.addOffice(deptFullname);

            String fullName = deptFullname.replaceAll("[\\+|\\s+]", "");
            String[] species = fullName.split("-");
            OfficeEntity company = this.officeService.getOfficeByName(species[0], null);

            if (office == null || company == null) {
                return;
            }
            System.out.println("公司【" + company.getId() + "】部门【" + office.getId() + "】");
            updateUser(lastUserInfo, jsonObject, company.getId(), office.getId(), userId, modified);
        }
    }


    public String getWorkPhone(String workPhone) {

        if (StringUtils.isNotBlank(workPhone)) {
            workPhone = workPhone.replaceAll("[^\\d|+]+", "");
            if (workPhone.length() < 7 || workPhone.matches("0+")) {
                workPhone = "";
                // 非0开头的号码需要处理
            } else if (workPhone.startsWith("0") == false) {
                if (workPhone.startsWith("1") && workPhone.length() == 11) {
                    workPhone = "";
                }
            }
            // 外国号码前面加拨3个000
            if (workPhone.startsWith("+") == false) {

                workPhone = workPhone.replace("+", "");
            }
        } else {

            workPhone = "";
        }
        return workPhone;
    }

    private void updateUser(UserEntity lastUserInfo, JSONObject jsonObject, String companyId, String officeId, String userId, final String modified) {
        DBHandler dBHandler = new DBHandler();
        Map<String, Object> columnMap = new TreeMap<String, Object>();
        Map<String, Object> whereMap = new TreeMap<String, Object>();

        // 字段和值绑定
        columnMap.put("id", jsonObject.get("employeeId"));
        columnMap.put("no", jsonObject.get("employeeId"));
        columnMap.put("full_office_name", jsonObject.get("deptFullname"));
        columnMap.put("name", jsonObject.get("name"));
        columnMap.put("mobile", jsonObject.get("mobile"));
        // 座机号与HRM的需要同步
        if (0 == lastUserInfo.getHuaweiUnicall()) {

            String workPhone = jsonObject.getString("workPhone");
            columnMap.put("phone", getWorkPhone(workPhone));
            columnMap.put("phone_number", Util.formatedWorkPhone(workPhone));
        }
        columnMap.put("email", jsonObject.get("email"));
        columnMap.put("update_date", jsonObject.get("operatorDate"));

        columnMap.put("office_id", officeId);

        columnMap.put("company_id", companyId);
        columnMap.put("login_name", jsonObject.get("account"));
        if (StringUtils.isEmpty(lastUserInfo.getPhoto())) {
            columnMap.put("photo", this.getPhoto(jsonObject.getString("sex")));
        }
        whereMap.put("id", userId);
        dBHandler.update(Constants.SYS_USER, columnMap, whereMap);

    }

    private UserEntity checkUserExist(String userId) throws SQLException {

        ResultSetHandler<List<UserEntity>> handler = new BeanListHandler<UserEntity>(UserEntity.class);
        String query = "SELECT *,huawei_unicall AS huaweiUnicall FROM sys_user WHERE id ='" + userId + "'";
        List<UserEntity> list = this.run.query(query, handler);

        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    private boolean checkUserProfileExist(String userId) throws SQLException {

        ResultSetHandler<List<UserEntity>> handler = new BeanListHandler<UserEntity>(UserEntity.class);
        String query = "SELECT * FROM sys_user_profiles WHERE user_id ='" + userId + "'";
        List<UserEntity> list = this.run.query(query, handler);

        if (list != null && list.size() > 0)
            return true;
        return false;
    }

    private enum MapType {
        resultOfficeEntityType, existOfficeEntityType, userEntityType;
    }

}
