package com.yeejoin.equipmanage.remote;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.component.feign.config.InnerInvokException;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.component.feign.utils.FeignUtil;
import com.yeejoin.amos.component.robot.AmosRequestContext;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.client.AgencyUserClient;
import com.yeejoin.amos.feign.privilege.model.*;
import com.yeejoin.amos.feign.privilege.util.PwdUtil;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
import com.yeejoin.equipmanage.common.entity.publics.CommonResponse;
import com.yeejoin.equipmanage.common.vo.Token;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.typroject.tyboot.core.foundation.context.RequestContext;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/***
 *
 * 平台安全接口实现类
 *
 * ***/
@Service("remoteSecurityService")
public class RemoteSecurityService {

    @Autowired
    AmosRequestContext amosRequestContext;
    @Value("${amos.system.user.password}")
    private String password;

    @Value("${security.productApp}")
    private String productApp;

    @Value("${amos.system.user.app-key}")
    private String appKeyApp;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private HttpServletRequest request;

    // * 根据公司id查询机构用户

    public List<AgencyUserModel> listUserByCompanyId(String companyId) {
        if (StringUtils.isEmpty(companyId)) {
            return null;
        }
        List<AgencyUserModel> AgencyUserModel = null;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Privilege.agencyUserClient.queryByCompanyId(Long.valueOf(companyId), null, null, true);
            AgencyUserModel = (List<AgencyUserModel>) feignClientResult.getResult();

        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return AgencyUserModel;
    }

    /**
     * 用户id批量获取用户信息
     *
     * @param userIds 用户ids
     * @return List<AgencyUserModel>
     */
    public List<AgencyUserModel> listUserByUserIds(String userIds) {
        List<AgencyUserModel> agencyUserModel = null;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Privilege.agencyUserClient.queryByIds(userIds, false);
            agencyUserModel = (List<AgencyUserModel>) feignClientResult.getResult();

        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return agencyUserModel;
    }

    /**
     * 部门id批量获取部门信息
     *
     * @param deptIds 部门ids
     * @return HashMap<String, String>
     */
    public List<HashMap<String, String>> listDeptByDeptIds(String deptIds) {
        List<HashMap<String, String>> agencyDeptModel;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Privilege.departmentClient.queryDeptByIds(deptIds);
            agencyDeptModel = (List<HashMap<String, String>>) feignClientResult.getResult();
        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return agencyDeptModel;
    }

    /**
     * 用户id获取用户信息
     *
     * @param userId 用户编号
     * @return AgencyUserModel
     */
    public AgencyUserModel getUserById(String userId) {
        if (StringUtils.isEmpty(userId)) {
            return null;
        }
        AgencyUserModel agencyUserModel;
        try {
            agencyUserModel = FeignUtil.remoteCall(() -> Privilege.agencyUserClient.queryByUserId(userId));
        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return agencyUserModel;
    }

    // 根据orgCode查询机构用户
    public List<AgencyUserModel> listUserByOrgCode(String orgCode) {
        if (StringUtils.isEmpty(orgCode)) {
            return null;
        }
        Set<AgencyUserModel> agencyUserModel;
        try {
            agencyUserModel = FeignUtil.remoteCall(() -> Privilege.agencyUserClient.queryByOrgCode(orgCode, null));
        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return new ArrayList<>(agencyUserModel);
    }

    // 根据部门id查询机构用户
    public List<AgencyUserModel> listUserByDepartmentId(Long departmentId) {
        if (departmentId == null) {
            return null;
        }
        List<AgencyUserModel> agencyUserModel;
        try {
            agencyUserModel = FeignUtil.remoteCall(() -> Privilege.agencyUserClient.queryByDepartmentId(departmentId, null, null, true));
        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return agencyUserModel;
    }

    // 根据orgCode查询机构
    public Map<String, Object> listByOrgCode(String orgCode) {
        if (StringUtils.isEmpty(orgCode)) {
            return null;
        }
        Map<String, Object> agencyUserModel = null;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Privilege.companyClient.queryByOrgcode(orgCode);
            agencyUserModel = (Map<String, Object>) feignClientResult.getResult();
        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return agencyUserModel;
    }

    // 查询指定公司的部门树
    public List<DepartmentModel> getDepartmentTreeByCompanyId(Long companyId) {
        if (companyId == null) {
            return null;
        }
        List<DepartmentModel> departmentModel = null;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Privilege.departmentClient.queryDeptTree(null, companyId);
            departmentModel = (List<DepartmentModel>) feignClientResult.getResult();
        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return departmentModel;

    }


    /**
     * 基础平台全部菜单权限树,用于平台登录前端初始化路由
     */
    public CommonResponse searchPermissionTree(long id, String appType) {
        List<PermissionModel> dictionarieModel = null;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Privilege.permissionClient.treeByRole(id, appType, null, null);
            dictionarieModel = (List<PermissionModel>) feignClientResult.getResult();

        } catch (InnerInvokException e) {
            throw new RuntimeException();
        }
        CommonResponse commonResponse = new CommonResponse("SUCCESS", dictionarieModel);
        return commonResponse;
    }

    /**
     * 根据Code查询指定的字典信息
     *
     * @param dictCode 字典编号
     * @return List<DictionarieValueModel>
     */
    public List<DictionarieValueModel> listDictionaryByDictCode(String dictCode) {
        List<DictionarieValueModel> dictionarieModel = null;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Systemctl.dictionarieClient.dictValues(dictCode);
            dictionarieModel = (List<DictionarieValueModel>) feignClientResult.getResult();

        } catch (InnerInvokException e) {
            throw new RuntimeException();
        }

        return dictionarieModel;
    }

    /**
     * 查询指定公司信息与其部门用户树
     */
    public CompanyModel listUserByCompanyId1(Long companyId) {
        if (companyId == null) {
            return null;
        }
        CompanyModel companyModel = null;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Privilege.companyClient.withDeptAndUsers(companyId);
            companyModel = (CompanyModel) feignClientResult.getResult();

        } catch (InnerInvokException e) {
            throw new RuntimeException();
        }
        return companyModel;

    }

    public JSONObject loginFromApp(String userName, String password) throws InnerInvokException,  IOException {
        IdPasswordAuthModel dPasswordAuthModel = new IdPasswordAuthModel();
        dPasswordAuthModel.setLoginId(userName);
        try {
            dPasswordAuthModel.setPassword(PwdUtil.encode(password));
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        FeignClientResult feignClientResult = new FeignClientResult();
        RequestContext.setProduct(productApp);
        RequestContext.setAppKey(appKeyApp);
        feignClientResult = Privilege.authClient.idpassword(dPasswordAuthModel);
        Map map = (Map) feignClientResult.getResult();
        if (map != null) {
            map.put("appKey", appKeyApp);
            map.put("product", productApp);
            String jsonStr = JSON.toJSONString(map);
            return JSONObject.parseObject(jsonStr);
        }
        return null;
    }

    public boolean loginOutFromApp(String toke, String product, String appKey) {

        boolean flag = false;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Privilege.authClient.removeToken();
            flag = true;
        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

        return flag;
    }

    public JSONArray listDepartmentUserTree(Long companyId) {

        CompanyModel companyModel = null;
        FeignClientResult feignClientResult;
        try {
            feignClientResult = Privilege.companyClient.withDeptAndUsers(companyId);
            companyModel = (CompanyModel) feignClientResult.getResult();

        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

        if (companyModel != null) {
            String jsonStr = null;

            jsonStr = JSON.toJSONString(companyModel.getChildren());

            return JSONArray.parseArray(jsonStr);
        }
        return null;

    }

    public boolean editPassword(String userId, String oldPassword, String newPassword) throws InnerInvokException {
        boolean flag = false;
        AgencyUserModel agencyUserModel = new AgencyUserModel();
        agencyUserModel.setPassword(newPassword);
        agencyUserModel.setRePassword(newPassword);
        agencyUserModel.setOriginalPassword(oldPassword);
        AgencyUserModel agencyUserModel2 = null;
        FeignClientResult feignClientResult;
        feignClientResult = Privilege.agencyUserClient.modifyPassword(userId, agencyUserModel);
        agencyUserModel = (AgencyUserModel) feignClientResult.getResult();
        if (agencyUserModel2 != null) {
            flag = true;
        }
        return false;
    }

    public FeignClientResult<Map<String, String>> fileImage(MultipartFile file) {
        String product = request.getHeader("product");
        String appKey = request.getHeader("appKey");
        try {
            RequestContext.setProduct(product);
            RequestContext.setAppKey(appKey);
            FeignClientResult<Map<String, String>> date = Systemctl.fileStorageClient.updateCommonFile(file);

            return date;
        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

    }

    public FeignClientResult<Map<String, String>> fileImage(MultipartFile[] files) {

        try {
            FeignClientResult<java.util.Map<String, String>> date = Systemctl.fileStorageClient
                    .updateCommonFiles(files);

            return date;
        } catch (InnerInvokException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

    }

    public AgencyUserModel getAgencyUser() {
        FeignClientResult<AgencyUserModel> agencyUser = null;
        AgencyUserModel userModel = null;
        try {
            AgencyUserClient agencyUserClient = Privilege.agencyUserClient;
            agencyUser = agencyUserClient.getme();
            userModel = agencyUser.getResult();
        } catch (InnerInvokException e) {
            e.printStackTrace();
        }
        return userModel;
    }

//    public Token getServerToken() {
//        IdPasswordAuthModel dPasswordAuthModel = new IdPasswordAuthModel();
//        dPasswordAuthModel.setLoginId(loginId);
//        dPasswordAuthModel.setPassword(DesUtil.encode(password, "qaz"));
//        Token toke = null;
//        try {
//            RedisTemplate redisTemplate1 = Redis.getRedisTemplate();
//            toke = JSON.parseObject(this.redisTemplate.opsForValue().get(buildKey(loginId)), Token.class);
//            if (ObjectUtils.isEmpty(toke)) {
//                toke = getLogin(dPasswordAuthModel);
//            } else {
//            	 RequestContext.setProduct(productWeb);
//                if (!TokenOperation.refresh(toke.getToke())) {
//                    toke = getLogin(dPasswordAuthModel);
//                }
//            }
//        } catch (InnerInvokException e) {
//            e.printStackTrace();
//        }
//        return toke;
//    }

    public Token getServerToken()  {
        IdPasswordAuthModel dPasswordAuthModel = new IdPasswordAuthModel();
        dPasswordAuthModel.setLoginId(amosRequestContext.getUserName());
        try {
            dPasswordAuthModel.setPassword(PwdUtil.encode(password));
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }  catch (IOException e) {
            e.printStackTrace();
        }
        Token toke = null;
        try {
            toke = JSON.parseObject(this.redisTemplate.opsForValue().get(buildKey(amosRequestContext.getUserName())), Token.class);
            if (ObjectUtils.isEmpty(toke)) {
                toke = getLogin(dPasswordAuthModel);
            } else {
                RequestContext.setProduct(amosRequestContext.getProduct());
                if (!redisUtils.refresh(toke.getToke())) {
                    toke = getLogin(dPasswordAuthModel);
                }
            }
        } catch (InnerInvokException e) {
            e.printStackTrace();
        }
        return toke;
    }

    //redis缓存系统用户token信息
    private String buildKey(String username) {
        return "system_" + username;
    }

    private Token getLogin(IdPasswordAuthModel dPasswordAuthModel) {
        Token toke = new Token();
        RequestContext.setProduct(amosRequestContext.getProduct());
        toke.setToke(amosRequestContext.getToken());
        toke.setProduct(amosRequestContext.getProduct());
        toke.setAppKey(amosRequestContext.getAppKey());
        redisTemplate.opsForValue().set(buildKey(dPasswordAuthModel.getLoginId()), JSONObject.toJSONString(toke), 28, TimeUnit.DAYS);
        return toke;
    }
}
