package com.kingdee.eas.custom.synctask;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.metadata.entity.*;
import com.kingdee.bos.metadata.query.util.CompareType;
import com.kingdee.eas.basedata.org.*;
import com.kingdee.eas.basedata.person.PersonInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.log.ISyncLog;
import com.kingdee.eas.custom.log.SyncLogFactory;
import com.kingdee.eas.custom.log.SyncLogInfo;
import com.kingdee.eas.custom.log.app.DataDirectionEnum;
import com.kingdee.eas.custom.log.app.DockingSystemEnum;
import com.kingdee.eas.custom.log.app.SyncEntityNameEnum;
import com.kingdee.eas.custom.log.app.SyncStatusEnum;
import com.kingdee.eas.custom.synctask.utils.GeneralUtils;
import com.kingdee.eas.hr.ats.AtsUtil;
import com.kingdee.eas.hr.base.EmployeeTypeInfo;
import com.kingdee.eas.hr.emp.IPersonPosition;
import com.kingdee.eas.hr.emp.PersonPositionCollection;
import com.kingdee.eas.hr.emp.PersonPositionFactory;
import com.kingdee.eas.hr.emp.PersonPositionInfo;
import com.kingdee.eas.utils.ExpiringMapCache;
import com.kingdee.util.DateTimeUtils;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.util.DigestUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * IOT平台同步事务
 */
public class SyncTranForIOTFacadeControllerBean extends AbstractSyncTranForIOTFacadeControllerBean {
    private static Logger logger = Logger.getLogger(SyncTranForIOTFacadeControllerBean.class);
    //缓存
    private static ExpiringMapCache<String, String> cache = new ExpiringMapCache();
    private Properties propt = new Properties();
    private static Map<String, Integer> adminOrgStatusMap = new HashMap<String, Integer>();

    public SyncTranForIOTFacadeControllerBean() throws BOSException {
        String syncOAConfigPath = System.getProperty("EAS_HOME") + "/server/properties/scy/syncIOTConfig.properties";
        try {
            propt.load(new FileInputStream(syncOAConfigPath));
        } catch (IOException e) {
            e.printStackTrace();
            String errorMsg = "获取配置文件报错，请检查配置：" + syncOAConfigPath + "   " + e.getMessage();
            throw new BOSException(errorMsg);
        }
    }

    private static Map<String, String> personStatusMap = new HashMap<String, String>();

    static {
        adminOrgStatusMap.put("集团", 1);//集团
        adminOrgStatusMap.put("公司", 2);//公司
        adminOrgStatusMap.put("一级组织", 3);//一级组织  区域
        adminOrgStatusMap.put("二级组织", 4);//二级组织  分公司
        adminOrgStatusMap.put("三级组织", 5);//三级组织  子公司
        adminOrgStatusMap.put("四级组织", 6);//四级组织  管理

        personStatusMap.put("001", "1");//正式员工
        personStatusMap.put("002", "1");//试用员工
        personStatusMap.put("006", "1");//待岗
        personStatusMap.put("007", "1");//长期病假
        personStatusMap.put("003", "1");//停薪留职
        personStatusMap.put("004", "1");//出国
        personStatusMap.put("013", "1");//返聘员工
        personStatusMap.put("031", "1");//长学
        personStatusMap.put("S01", "1");//实习生
        personStatusMap.put("S02", "1");//劳务派遣
        personStatusMap.put("035", "1");//待分配
        personStatusMap.put("S20", "1");//顾问
        personStatusMap.put("S06", "1");//临时工


        personStatusMap.put("009", "3");//辞职
        personStatusMap.put("010", "3");//辞退
        personStatusMap.put("011", "3");//退休
        personStatusMap.put("005", "3");//下岗
        personStatusMap.put("012", "3");//离休
        personStatusMap.put("020", "3");//开除
        personStatusMap.put("021", "3");//解聘
        personStatusMap.put("030", "3");//失踪
        personStatusMap.put("031", "3");//死亡
        personStatusMap.put("S08", "3");//返聘终止
        personStatusMap.put("S09", "3");//离职
        personStatusMap.put("S05", "3");//派遣终止
        personStatusMap.put("S07", "3");//临时工终止
        personStatusMap.put("S03", "3");//实习终止
    }

    /**
     * Iot平台部门信息同步
     *
     * @param ctx
     * @param billds
     * @throws BOSException
     */
    @Override
    protected Map _syncOrgUnitToIot(Context ctx, String billds) throws BOSException {
        SyncLogInfo syncLogInfo = new SyncLogInfo();
        syncLogInfo.setEntityName(SyncEntityNameEnum.adminOrg);
        syncLogInfo.setDataDirection(DataDirectionEnum.outflow);
        syncLogInfo.setDockingSystem(DockingSystemEnum.IOT);
        //String billds = request.getParameter("billIds");
        try {

            logger.error("_syncOrgUnitToOA---start");
            logger.error("_syncOrgUnitToOA---billds: " + billds);
            IAdminOrgUnit iAdminOrgUnit = AdminOrgUnitFactory.getLocalInstance(ctx);
            //String actionType = action == null ? "" : action.getValue().toLowerCase();
            //当参数billIds不为空值时，增量同步参数中的部门数据到OA
            FilterInfo filterInfo = new FilterInfo();
            FilterItemCollection filterItems = filterInfo.getFilterItems();
            filterItems.add(new FilterItemInfo("id", "00000000-0000-0000-0000-000000000000CCE7AED4", CompareType.NOTEQUALS));
            if (!StringUtils.isEmpty(billds)) {
                Set<String> adminOrgIds = AtsUtil.toSet(billds);
                logger.error("_syncOrgUnitToOA---adminOrgIds---" + adminOrgIds);
                filterItems.add(new FilterItemInfo("id", adminOrgIds, CompareType.INCLUDE));
            }
            SelectorItemCollection sic = new SelectorItemCollection();
            sic.add("*");
            sic.add("parent.number");
            sic.add("parent.id");
            sic.add("responPosition.name");
            sic.add("responPosition.number");
            sic.add("unitLayerType.number");
            sic.add("unitLayerType.name");
            EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
            AdminOrgUnitCollection adminOrgUnitCollection = iAdminOrgUnit.getAdminOrgUnitCollection(entityViewInfo);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("dataSyncRule", 1);//1：组织ID存在时更新 2：组织ID存在时跳过不更新。默认值1
            List dataList = new ArrayList();

            for (int i = 0; i < adminOrgUnitCollection.size(); i++) {
                Map adminMap = new HashMap();
                AdminOrgUnitInfo adminOrgUnitInfo = adminOrgUnitCollection.get(i);
                OrgUnitLayerTypeInfo unitLayerType = adminOrgUnitInfo.getUnitLayerType();//行政组织类型
                String number = unitLayerType.getNumber();
                String adminOrgType = String.valueOf(adminOrgStatusMap.getOrDefault(number, 8));
                adminMap.put("id", adminOrgUnitInfo.getId().toString());//来源方组织ID
                adminMap.put("code", adminOrgUnitInfo.getNumber());//组织编码
                adminMap.put("name", adminOrgUnitInfo.getName());//组织名称
                adminMap.put("type", adminOrgType);//组织类型
                adminMap.put("order", String.valueOf(adminOrgUnitInfo.getIndex()));//序号
                adminMap.put("description", "");//描述信息
                adminMap.put("parentId", adminOrgUnitInfo.getParent().getId().toString());//来源方上级组织ID
                Map params = new HashMap();
                boolean isSealUp = adminOrgUnitInfo.isIsSealUp();
                params.put("status", isSealUp ? "1" : "0");
                adminMap.put("params", params);//组织参数（扩展字段）
                dataList.add(adminMap);
            }
            jsonObject.put("data", dataList);//1：组织ID存在时更新 2：组织ID存在时跳过不更新。默认值1
            //执行同步组织到Iot
            return syncOrg(jsonObject.toString(), syncLogInfo, ctx);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BOSException(e.getMessage());
        }
    }

    /**
     * Iot平台人员信息同步
     *
     * @param ctx
     * @param billds
     * @throws BOSException
     */
    @Override
    protected Map _syncPersonToIot(Context ctx, String billds) throws BOSException, EASBizException {
        ISyncLog iSyncLog = SyncLogFactory.getLocalInstance(ctx);
        SyncLogInfo syncLogInfo = new SyncLogInfo();
        syncLogInfo.setEntityName(SyncEntityNameEnum.person);
        syncLogInfo.setDataDirection(DataDirectionEnum.outflow);
        syncLogInfo.setDockingSystem(DockingSystemEnum.IOT);
        IPersonPosition iPersonPosition = PersonPositionFactory.getLocalInstance(ctx);
        try {
            //IPerson iPerson = PersonFactory.getLocalInstance(ctx);
            FilterInfo filterInfo = new FilterInfo();
            FilterItemCollection filterItems = filterInfo.getFilterItems();
            Set personIds = new HashSet();
            //如果为空查询所有数据
            if (!StringUtils.isEmpty(billds)) {
                //PersonCollection personCollection = iPerson.getPersonCollection("select id,number");
                //StringBuilder sb = new StringBuilder();
                //for (int i = 0; i < personCollection.size(); i++) {
                //    PersonInfo personInfo = personCollection.get(i);
                //    String personId = personInfo.getId().toString();
                //    sb.append(personId).append(",");
                //}
                //sb.deleteCharAt(sb.lastIndexOf(","));
                //billds = sb.toString();
                personIds = AtsUtil.toSet(billds);
                logger.error("syncPersonToIot---personIds---" + personIds);
                filterItems.add(new FilterItemInfo("person", personIds, CompareType.INCLUDE));
            }
            SelectorItemCollection sic = new SelectorItemCollection();
            sic.add("*");
            sic.add("person.number");
            sic.add("person.name");
            sic.add("person.id");
            sic.add("person.hireDate");
            sic.add("person.nCell");
            sic.add("person.gender");
            sic.add("person.email");
            sic.add("person.employeeType.number");
            sic.add("personDep.name");
            sic.add("personDep.number");
            sic.add("personDep.id");
            sic.add("personDep.parent.id");
            EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
            PersonPositionCollection personPositionCollection = iPersonPosition.getPersonPositionCollection(entityViewInfo);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("dataSyncRule", 1);//1：组织ID存在时更新 2：组织ID存在时跳过不更新。默认值1
            List dataList = new ArrayList();
            for (int i = 0; i < personPositionCollection.size(); i++) {
                Map personMap = new HashMap();
                PersonPositionInfo personPositionInfo = personPositionCollection.get(i);
                PersonInfo person = personPositionInfo.getPerson();
                //personMap.put("id", person.getId().toString());//来源方用户ID
                personMap.put("id", person.getNumber());//来源方用户ID
                personMap.put("name", person.getName());//用户姓名
                personMap.put("phone", person.getNCell());//手机号
                personMap.put("gender", person.getGender() == null ? null : person.getGender().getValue());//性别
                //personMap.put("email", person.getEmail());//邮箱
                EmployeeTypeInfo employeeType = person.getEmployeeType();
                String number = employeeType.getNumber();
                String personStatus = personStatusMap.get(number);
                //调用新增接口---禁用系统用户账号 状态等于3属于离职人员
                if ("3".equals(personStatus)) {
                    logger.error("personStatus=3" + person.getName());
                    //调用禁用用户接口
                    GeneralUtils generalUtils = new GeneralUtils();
                    generalUtils.disableUserAccount(ctx, person);
                }
                personMap.put("status", personStatus);//状态
                AdminOrgUnitInfo personDep = personPositionInfo.getPersonDep();
                List orgIds = new ArrayList();
                orgIds.add(personDep.getId().toString());
                personMap.put("orgIds", orgIds);//来源方组织ID列表
                dataList.add(personMap);
                //员工编码
                Map paramsMap = new HashMap();
                paramsMap.put("employeeNo", person.getNumber());
                Date hireDate = person.getHireDate();
                if (hireDate != null) {
                    String entryDate = DateTimeUtils.format(hireDate, "yyyy-MM-dd");
                    paramsMap.put("entryDate", entryDate);
                }
                personMap.put("params", paramsMap);
                personMap.put("areaCode", "+86");
            }
            jsonObject.put("data", dataList);//1：组织ID存在时更新 2：组织ID存在时跳过不更新。默认值1
            syncLogInfo.setRequestParams(jsonObject.toString());
            //执行同步人员到Iot
            syncLogInfo.setSyncCount(personIds.size());
            //部署需要替换 syncPerson(ctx, jsonObject.toString(), syncLogInfo);
            return syncPerson(ctx, jsonObject.toString(), syncLogInfo);
            //return new HashMap();
        } catch (Exception e) {
            e.printStackTrace();
            syncLogInfo.setSyncStatus(SyncStatusEnum.ERROR);
            syncLogInfo.setSyncResult(e.getMessage());
            iSyncLog.save(syncLogInfo);
            throw new BOSException(e);
        }
    }

    /**
     * 获取token
     * 本地缓存token，有效时长6.5小时
     *
     * @return
     */
    public String getToken() throws BOSException {
        String token = cache.get("token");
        if (StringUtils.isBlank(token)) {
            token = getTokenByRemote();
        }
        return token;
    }

    /**
     * 请求方法
     *
     * @param data
     */
    public Map<String, String> syncPerson(Context ctx, String data, SyncLogInfo syncLogInfo) throws BOSException, EASBizException {
        Response response = null;
        Map<String, String> result = new HashMap<String, String>();
        try {
            String syncOrgUnitApiUrl = this.propt.getProperty("syncUserApiUrl");
            //String syncOrgUnitApiUrl = "http://10.0.3.87/api/open/enterpriseright/org-manage/v1/external/org/batch";
            if (org.apache.commons.lang3.StringUtils.isBlank(syncOrgUnitApiUrl)) {
                throw new BOSException("syncOrgUnitApiUrl不能为空！");
            }
            logger.error("syncPerson---data-----" + data);
            OkHttpClient client = new OkHttpClient();
            MediaType mediaType = MediaType.parse("application/json");
            RequestBody body = RequestBody.create(mediaType, data);
            Request request = new Request.Builder()
                    .url(syncOrgUnitApiUrl)
                    .post(body)
                    //.addHeader("Authorization", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ2UzVMT29mYiIsInNlcnZlciI6dHJ1ZSwidXNlcl9uYW1lIjoic0hSIiwicHJvamVjdE1hcCI6IntcIlNDWVwiOlwiMTMwMDgwNTYwNDAwNDA0NDgwMFwifSIsInNjb3BlIjpbInNlcnZlciJdLCJuYW1lIjoic0hSIiwicHJvamVjdCI6IiIsImV4cCI6MTczMDkxMzQwOSwidGVuYW50IjoidGFpb3QiLCJjbGllbnRfaWQiOiJzeXMifQ.hS1LVZ56rHPvVZmRdipay3XNAmmtFBZKt-wPc7UK2rg ")
                    .addHeader("Authorization", getToken())
                    .addHeader("Accept", "*/*")
                    .addHeader("User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0")
                    .addHeader("Connection", "keep-alive")
                    .addHeader("Content-Type", "application/json")
                    .build();
            response = client.newCall(request).execute();
            String string = response.body().string();
            logger.error("string-----" + string);
            int success = 0;
            int fail = 0;
            if (response.isSuccessful()) {
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, List<Map<String, String>>> resultMap = objectMapper.readValue(string, Map.class);
                List<Map<String, String>> list = resultMap.get("data");
                for (int i = 0; i < list.size(); i++) {
                    Map<String, String> map = list.get(i);
                    result.put(map.get("id"), map.get("msg"));
                    if (map.get("code") != null) {
                        if (map.get("code").equals("1")) {
                            success++;
                        } else {
                            fail++;
                        }
                    } else {
                        fail++;
                    }
                }
                //todo
                //return (String) result.get("token");
                syncLogInfo.setSyncStatus(SyncStatusEnum.SUCCESS);
                //syncLogInfo.setSyncCount(total);
                syncLogInfo.setSuccessNum(success);
                syncLogInfo.setFailNum(fail);
                syncLogInfo.setSyncResult(result.toString());
                SyncLogFactory.getLocalInstance(ctx).save(syncLogInfo);
            } else {
                syncLogInfo.setSyncStatus(SyncStatusEnum.ERROR);
                syncLogInfo.setSuccessNum(success);
                syncLogInfo.setFailNum(fail);
                syncLogInfo.setSyncResult(result.toString());
                SyncLogFactory.getLocalInstance(ctx).save(syncLogInfo);
            }
        } catch (IOException e) {
            e.printStackTrace();
            syncLogInfo.setSyncStatus(SyncStatusEnum.ERROR);
            syncLogInfo.setFailNum(syncLogInfo.getSyncCount());
            syncLogInfo.setSyncResult(result.toString());
            syncLogInfo.setRequestParams(e.getMessage());
            SyncLogFactory.getLocalInstance(ctx).save(syncLogInfo);
            throw new RuntimeException("同步IOT平台人员失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 请求方法
     *
     * @param data
     */
    public Map syncOrg(String data, SyncLogInfo syncLogInfo, Context ctx) throws BOSException, EASBizException {
        Response response = null;
        Map result = null;
        try {
            String syncOrgUnitApiUrl = this.propt.getProperty("syncOrgUnitApiUrl");
            //String syncOrgUnitApiUrl = "http://10.0.3.87/api/open/enterpriseright/org-manage/v1/external/org/batch";
            if (StringUtils.isBlank(syncOrgUnitApiUrl)) {
                throw new BOSException("syncOrgUnitApiUrl不能为空！");
            }
            logger.error("syncOrg---data-----" + data);
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .build();
            MediaType mediaType = MediaType.parse("application/json");
            RequestBody body = RequestBody.create(mediaType, data);
            Request request = new Request.Builder()
                    .url(syncOrgUnitApiUrl)
                    .post(body)
                    //.addHeader("Authorization", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ2UzVMT29mYiIsInNlcnZlciI6dHJ1ZSwidXNlcl9uYW1lIjoic0hSIiwicHJvamVjdE1hcCI6IntcIlNDWVwiOlwiMTMwMDgwNTYwNDAwNDA0NDgwMFwifSIsInNjb3BlIjpbInNlcnZlciJdLCJuYW1lIjoic0hSIiwicHJvamVjdCI6IiIsImV4cCI6MTczMDkxMzQwOSwidGVuYW50IjoidGFpb3QiLCJjbGllbnRfaWQiOiJzeXMifQ.hS1LVZ56rHPvVZmRdipay3XNAmmtFBZKt-wPc7UK2rg ")
                    .addHeader("Authorization", getToken())
                    .addHeader("Accept", "*/*")
                    .addHeader("User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0")
                    .addHeader("Connection", "keep-alive")
                    .addHeader("Content-Type", "application/json")
                    .build();
            response = client.newCall(request).execute();
            String string = response.body().string();
            logger.error("string--" + string);
            syncLogInfo.setSyncResult(string);
            ObjectMapper objectMapper = new ObjectMapper();
            result = objectMapper.readValue(string, Map.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("同步IOT平台组织失败: " + e.getMessage());
        }
        logger.error("result-----" + result);
        logger.error("response.isSuccessful()-----" + response.isSuccessful());
        int success = 0;
        int fail = 0;
        if (response.isSuccessful()) {
            List<Map<String, String>> list = (List<Map<String, String>>) result.get("data");
            for (int i = 0; i < list.size(); i++) {
                Map<String, String> map = list.get(i);
                if (map.get("code").equals("1")) {
                    success++;
                } else {
                    fail++;
                }
            }
            //return (String) result.get("token");
            syncLogInfo.setSyncStatus(SyncStatusEnum.SUCCESS);
            //syncLogInfo.setSyncCount(total);
            syncLogInfo.setSuccessNum(success);
            syncLogInfo.setFailNum(fail);

            SyncLogFactory.getLocalInstance(ctx).save(syncLogInfo);
        } else {
            syncLogInfo.setSyncStatus(SyncStatusEnum.ERROR);
            syncLogInfo.setSuccessNum(success);
            syncLogInfo.setFailNum(fail);
            syncLogInfo.setSyncResult(result.toString());
            SyncLogFactory.getLocalInstance(ctx).save(syncLogInfo);
        }
        return result;
    }


    /**
     * 远程获取Token
     *
     * @return
     */
    private String getTokenByRemote() throws BOSException {
        Response response = null;
        Map result = null;
        try {
            long now = System.currentTimeMillis();
            Map<String, String> params = new HashMap<String, String>();
            String getTokenApiUrl = this.propt.getProperty("getTokenApiUrl");
            if (StringUtils.isBlank(getTokenApiUrl)) {
                throw new BOSException("获取token接口地址不能为空！");
            }
            String appid = this.propt.getProperty("appid");
            if (StringUtils.isBlank(appid)) {
                throw new BOSException("appid不能为空！");
            }
            String secret = this.propt.getProperty("secret");
            if (StringUtils.isBlank(secret)) {
                throw new BOSException("secret不能为空！");
            }
            params.put("appid", appid);
            params.put("sign_method", "md5");
            params.put("timestamp", now + secret);
            //生成签名
            String sign = DigestUtils.md5DigestAsHex((appendUrl(null, params)).getBytes());
            params.put("timestamp", String.valueOf(now));
            params.put("sign", sign);
            String requestUrl = appendUrl(getTokenApiUrl, params);
            logger.error("getTokenByRemote -> requestUrl " + requestUrl);
            OkHttpClient client = new OkHttpClient().newBuilder()
                    .build();
            Request request = new Request.Builder()
                    .url(requestUrl)
                    .get()
                    .build();
            response = client.newCall(request).execute();
            String string = response.body().string();
            ObjectMapper objectMapper = new ObjectMapper();
            result = objectMapper.readValue(string, Map.class);
            logger.error("getTokenByRemote -> result " + result);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BOSException("远程获取IOT平台token失败: " + e.getMessage());
        }
        if (response.isSuccessful()) {
            String token = (String) result.get("token");
            //缓存token
            cache.put("token", token, 27000000);//6.5小时
            return token;
        } else {
            throw new BOSException((String) result.get("msg"));
        }
    }

    /**
     * 拼接地址参数
     */
    private String appendUrl(String url, Map<String, String> data) {
        StringBuilder paramStr = new StringBuilder();
        for (String key : data.keySet()) {
            paramStr.append(key).append("=").append(data.get(key)).append("&");
        }
        paramStr.deleteCharAt(paramStr.lastIndexOf("&"));
        if (!StringUtils.isEmpty(url)) {
            return url.contains("?") ? (url + "&" + paramStr) : (url + "?" + paramStr);
        }
        return paramStr.toString();
    }


}
