package com.yeejoin.amos.maintenance.core.framework;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.DepartmentBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.bo.RoleBo;
import com.yeejoin.amos.component.feign.config.InnerInvokException;
import com.yeejoin.amos.component.feign.config.TokenOperation;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.amos.feign.privilege.model.DepartmentModel;
import com.yeejoin.amos.feign.privilege.model.RoleModel;
import com.yeejoin.amos.maintenance.exception.PermissionException;
import com.yeejoin.amos.maintenance.feign.RemoteSecurityService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.typroject.tyboot.core.foundation.context.RequestContext;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

@Aspect
@Component
@ResponseBody
public class PermissionAspect {
    private static final Logger logger = LoggerFactory.getLogger(PermissionAspect.class);

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RemoteSecurityService remoteSecurityService;

    @Before(value = "@annotation(Permission) && @annotation(permission)")
    public void PermissionCheck(JoinPoint joinPoint, Permission permission) throws PermissionException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        logger.info("======开始权限校验======");
        String token = request.getHeader("token");
        token = ObjectUtils.isEmpty(token) ? request.getHeader("X-Access-Token") : token;
        String product = request.getHeader("product");
        String appKey = request.getHeader("appKey");
        RequestContext.setToken(token);
        RequestContext.setProduct(product);
        RequestContext.setAppKey(appKey);
        if (!TokenOperation.refresh(token)) {
            throw new PermissionException("登录信息失效，请重新登录");
        }
        FeignClientResult feignClientResult;
        AgencyUserModel userModel = null;
        try {
            feignClientResult = Privilege.agencyUserClient.getme();
            userModel = (AgencyUserModel) feignClientResult.getResult();
        } catch (InnerInvokException e) {
            throw new PermissionException("用户信息校验失败");
        }
        if (userModel == null) {
            throw new PermissionException("用户信息校验失败");
        }
        String name = "";
        String companyId = "";
        String type = "";
        if (permission.isPersonIdentity()) {
            //调用jcs，进行人员身份判断，是维保公司人员还是业主单位人员
            JSONObject result = new JSONObject();
            name = result.get("name").toString();
            companyId = result.get("companyId").toString();
            type = result.get("type").toString();
        }
        ReginParams regionParam = new ReginParams();
        String userId = userModel.getUserId();
        Map<Long, List<RoleModel>> orgRoles = userModel.getOrgRoles();
        ReginParams reginParams = JSON.parseObject(redisTemplate.opsForValue().get(buildKey(userModel.getUserId(), token)), ReginParams.class);
        if (reginParams == null && userModel.getCompanys().size() > 0) {
            CompanyModel companyModel = userModel.getCompanys().get(0);
            List<DepartmentModel> deptList = remoteSecurityService.getDepartmentTreeByCompanyId(token, product, appKey, companyModel.getSequenceNbr().toString());
            regionParam.setPersonIdentity(new ReginParams.PersonIdentity(type, name, companyId));
            if (deptList.size() > 0) {
                CompanyBo companyBo = convertCompanyModelToBo(companyModel);
                DepartmentBo departmentBo = convertDepartmentModelToBo(deptList.get(0));
                regionParam.setCompany(companyBo);
                regionParam.setDepartment(departmentBo);
                if (!ObjectUtils.isEmpty(orgRoles) && !orgRoles.get(departmentBo.getSequenceNbr()).isEmpty()) {
                    regionParam.setRole(convertRoleModelToBo(orgRoles.get(departmentBo.getSequenceNbr()).get(0)));
                }
            } else {
                if (!ObjectUtils.isEmpty(userModel.getOrgRoles()) && !ObjectUtils.isEmpty(companyModel) && userModel.getOrgRoles().get(companyModel.getSequenceNbr()).size() > 0) {
                    RoleModel role = userModel.getOrgRoles().get(companyModel.getSequenceNbr()).get(0);
                    RoleBo roleBo = new RoleBo();
                    BeanUtils.copyProperties(role, roleBo);
                    regionParam.setRole(roleBo);
                }
            }
            redisTemplate.opsForValue().set(buildKey(userId, token), JSONObject.toJSONString(regionParam));
        }
    }


    private DepartmentBo convertDepartmentModelToBo(DepartmentModel departmentModel) {
        DepartmentBo departmentBo = new DepartmentBo();
        if (departmentModel != null) {
            departmentBo.setCompanySeq(departmentModel.getCompanySeq());
            departmentBo.setDepartmentDesc(departmentModel.getDepartmentDesc());
            departmentBo.setDepartmentName(departmentModel.getDepartmentName());
            departmentBo.setLevel(departmentModel.getLevel());
            departmentBo.setOrgCode(departmentModel.getOrgCode());
            departmentBo.setParentId(departmentModel.getParentId());
            departmentBo.setDeptOrgCode(departmentModel.getDeptOrgCode());
            departmentBo.setSequenceNbr(departmentModel.getSequenceNbr());
        }
        return departmentBo;
    }

    /**
     * Model 转 Bo
     */
    private CompanyBo convertCompanyModelToBo(CompanyModel companyModel) {

        CompanyBo companyBo = new CompanyBo();
        if (companyModel != null) {
            companyBo.setAddress(companyModel.getAddress());
            companyBo.setCompanyName(companyModel.getCompanyName());
            companyBo.setCompanyOrgCode(companyModel.getCompanyOrgCode());
            companyBo.setEmail(companyModel.getEmail());
            companyBo.setLandlinePhone(companyModel.getLandlinePhone());
            companyBo.setLongitude(companyModel.getLongitude());
            companyBo.setLatitude(companyModel.getLatitude());
            companyBo.setLevel(companyModel.getLevel());
            companyBo.setOrgCode(companyModel.getOrgCode());
            companyBo.setSequenceNbr(companyModel.getSequenceNbr());
            companyBo.setParentId(companyModel.getParentId());
        }
        return companyBo;
    }

    private RoleBo convertRoleModelToBo(RoleModel roleModel) {
        RoleBo roleBo = new RoleBo();
        if (roleModel != null) {
            roleBo.setRoleName(roleModel.getRoleName());
            roleBo.setRoleType(roleModel.getRoleType());
            roleBo.setSequenceNbr(roleModel.getSequenceNbr());
        }
        return roleBo;
    }

    /**
     * redis缓存选择的用户信息
     *
     * @param userId userId
     * @param token  token
     * @return String
     */
    private String buildKey(String userId, String token) {
        return "region_" + userId + "_" + token;

    }
}
