
package cn.ibizlab.api.rest.extensions;

import cn.ibizlab.core.uaa.service.ISYS_PERMISSIONService;
import cn.ibizlab.util.client.IBZOUFeignClient;
import cn.ibizlab.util.security.AuthTokenUtil;
import cn.ibizlab.util.security.AuthenticationInfo;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.security.AuthorizationLogin;
import cn.ibizlab.util.service.AuthenticationUserService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 客户端登录认证
 */
@RestController
@RequestMapping("/")
public class ClientAuthenticationResource
{

    @Value("${ibiz.jwt.header:Authorization}")
    private String tokenHeader;

    @Autowired
    private AuthTokenUtil jwtTokenUtil;

    /**
     * 实体操作标识
     */
    private String OPPriTag="OPPRIV";
    /**
     * 统一资源标识
     */
    private String UniResTag="UNIRES";
    /**
     * 菜单项标识
     */
    private String AppMenuTag="APPMENU";

    @Autowired
    @Qualifier("IBZUSERService")
    private AuthenticationUserService userDetailsService;

    @Autowired
    private IBZOUFeignClient ouFeignClient;

    @Autowired
    private ISYS_PERMISSIONService permissionService;

    @PostMapping(value = "v7/login")
    public ResponseEntity<AuthenticationInfo> login(@Validated @RequestBody AuthorizationLogin authorizationLogin){
        userDetailsService.resetByUsername(authorizationLogin.getUsername());
        AuthenticationUser user = userDetailsService.loadUserByLogin(authorizationLogin.getUsername(),authorizationLogin.getPassword());
        if(user.getPermissionList()==null)
        {
            setUserPermission(user);
            setUserOrgInfo(user);
        }
        final String token = jwtTokenUtil.generateToken(user);
        // 返回 token
        return ResponseEntity.ok().body(new AuthenticationInfo(token,user));
    }

    @PostMapping(value = "uaa/login")
    public ResponseEntity<AuthenticationUser> uaalogin(@Validated @RequestBody AuthorizationLogin authorizationLogin){
        userDetailsService.resetByUsername(authorizationLogin.getUsername());
        AuthenticationUser user = userDetailsService.loadUserByLogin(authorizationLogin.getUsername(),authorizationLogin.getPassword());
        if(user.getPermissionList()==null)
        {
            setUserPermission(user);
            setUserOrgInfo(user);
        }
        return ResponseEntity.ok().body(user);
    }


    @PostMapping(value = "uaa/loginbyusername")
    public ResponseEntity<AuthenticationUser> loginByUsername(@Validated @RequestBody String username){
        //userDetailsService.resetByUsername(authorizationLogin.getUsername());
        AuthenticationUser user = userDetailsService.loadUserByUsername(username);
        if(user.getPermissionList()==null)
        {
            setUserPermission(user);
            setUserOrgInfo(user);
        }
        return ResponseEntity.ok().body(user);
    }

    /**
     * 设置用户权限
     * @param user
     * @return
     */
    public void setUserPermission(AuthenticationUser user) {

        JSONObject permissionObj=new JSONObject();

        //数据能力
        String opprivSQL="SELECT\n" +
                "\tT2.pssysmoduleid as sysmodule,\n" +
                "\tT2.psdataentityid as dataentity,\n" +
                "\tT2.pssourceid as pssourceid,\n" +
                "\tT2.pssourcetype as pssourcetype,\n" +
                "\tT2.psdedatarangeid as dedatarange,\n" +
                "\tT1.sys_permissionname\n" +
                "FROM\n" +
                "\tibzrole_permission T\n" +
                "INNER JOIN ibzpermission T1 ON T.SYS_PERMISSIONID = T1.SYS_PERMISSIONID\n" +
                "INNER JOIN ibzpsdeoppriv T2 on T1.SYS_PERMISSIONID=t2.SYS_PSDEOPPRIVID\n" +
                "WHERE\n" +
                "\tT.SYS_ROLEID IN (\n" +
                "\t SELECT  SYS_ROLEID\n" +
                "\t FROM\n" +
                "\t IBZUSER_ROLE t LEFT JOIN IBZUSER  t1 ON t.SYS_USERID=T1.USERID\n" +
                "\t WHERE\n" +
                "\t T1.USERID = #{et.param0}\n" +
                "\t)\n" +
                "AND T1.PERMISSIONTYPE = #{et.param1} ";

        //统一资源
        String uniResSQL="SELECT\n" +
                "\tt2.SYS_PSSYSUNIRESID,\n" +
                "\tt2.SYS_PSSYSUNIRESNAME,\n" +
                "\tT2.UNIRESCODE \n" +
                "FROM\n" +
                "\tibzrole_permission T\n" +
                "INNER JOIN ibzpermission T1 ON T.SYS_PERMISSIONID = T1.SYS_PERMISSIONID\n" +
                "INNER JOIN IBZPSSYSUNIRES T2 on T1.SYS_PERMISSIONID=t2.SYS_PSSYSUNIRESID\n" +
                "WHERE\n" +
                "\tT.SYS_ROLEID IN (\n" +
                "\t SELECT  SYS_ROLEID\n" +
                "\t FROM\n" +
                "\t IBZUSER_ROLE t LEFT JOIN IBZUSER  t1 ON t.SYS_USERID=T1.USERID\n" +
                "\t WHERE\n" +
                "\t T1.USERID = #{et.param0}\n" +
                "\t)\n" +
                "AND T1.PERMISSIONTYPE = #{et.param1} ";

        //应用菜单
        String appMenuSQL="SELECT\n" +
                "\tt2.PSAPPMENUITEMID as MENUITEMID,\n" +
                "\tt2.SYS_PSAPPMENUITEMNAME AS MENUITEMNAME \n" +
                "FROM\n" +
                "\tibzrole_permission T\n" +
                "INNER JOIN ibzpermission T1 ON T.SYS_PERMISSIONID = T1.SYS_PERMISSIONID\n" +
                "INNER JOIN ibzpsappmenuitem T2 on T1.SYS_PERMISSIONID=t2.SYS_PSAPPMENUITEMID\n" +
                "WHERE\n" +
                "\tT.SYS_ROLEID IN (\n" +
                "\t SELECT  SYS_ROLEID\n" +
                "\t FROM\n" +
                "\t IBZUSER_ROLE t LEFT JOIN IBZUSER  t1 ON t.SYS_USERID=T1.USERID\n" +
                "\t WHERE\n" +
                "\t T1.USERID = #{et.param0}\n" +
                "\t)\n" +
                "AND T1.PERMISSIONTYPE = #{et.param1} ";


        Map opprivParam=new HashMap();
        opprivParam.put("param0",user.getUserid());
        opprivParam.put("param1",OPPriTag);

        Map uniresParam=new HashMap();
        uniresParam.put("param0",user.getUserid());
        uniresParam.put("param1",UniResTag);

        Map appMenuParam=new HashMap();
        appMenuParam.put("param0",user.getUserid());
        appMenuParam.put("param1",AppMenuTag);

        List<JSONObject> entitiesList= permissionService.select(opprivSQL,opprivParam); //查询用户权限下数据能力
        List<JSONObject> uniResList= permissionService.select(uniResSQL,uniresParam);   //查询用户权限下的统一资源
        List<JSONObject> appMenuItemList= permissionService.select(appMenuSQL,appMenuParam); //查询用户权限下的菜单项

        JSONObject entities=getEntitiesList(entitiesList);
        JSONArray uniRes=getUniRes(uniResList);
        JSONArray appMenuItem=getAppMenuItem(appMenuItemList);

        permissionObj.put("entities",entities);
        permissionObj.put("unires",uniRes);
        permissionObj.put("appmenu",appMenuItem);
        user.setPermissionList(permissionObj);
    }

    /**
     * 获取应用菜单
     * @param menuItemList
     * @return
     */
    private JSONArray getAppMenuItem(List<JSONObject> menuItemList) {
        JSONArray menuItemArr=new JSONArray();
        for(int a=0;a<menuItemList.size();a++){
            JSONObject menuItem=menuItemList.get(a);
            JSONObject newMenuItem=new JSONObject();
            newMenuItem.put("menuitemid",menuItem.getString("MENUITEMID"));
            newMenuItem.put("menuitemname",menuItem.getString("MENUITEMNAME"));
            menuItemArr.add(newMenuItem);
        }
        return menuItemArr;
    }

    /**
     * 获取统一资源
     * @param uniResList
     * @return
     */
    private JSONArray getUniRes(List<JSONObject> uniResList) {

        JSONArray uniResArr=new JSONArray();
        for(int a=0;a<uniResList.size();a++){
            JSONObject uniRes=uniResList.get(a);
            JSONObject newUniRes=new JSONObject();
            newUniRes.put("unirescode",uniRes.getString("UNIRESCODE"));
            newUniRes.put("uniresname",uniRes.getString("SYS_PSSYSUNIRESNAME"));
            uniResArr.add(newUniRes);
        }
        return uniResArr;
    }

    /**
     * 拼接实体行为资源
     * @param role_permissions
     * @return
     */
    private JSONObject getEntitiesList(List<JSONObject> role_permissions) {

        JSONObject permission_entity= new JSONObject();
        for (Map rolePermission : role_permissions) {
            JSONObject obj = JSONObject.parseObject(JSONObject.toJSON(rolePermission).toString());
            String entityName = obj.getString("dataentity");
            String dataRangeName = obj.getString("dedatarange");
            String sourceName = obj.getString("pssourceid");
            String sourceType=obj.getString("pssourcetype");
            JSONObject entity = new JSONObject();
            JSONObject permission = new JSONObject();
            JSONArray dataRange = new JSONArray();

            if (permission_entity.containsKey(entityName))//实体合并
                entity = permission_entity.getJSONObject(entityName);

            if (entity.containsKey(sourceType))//数据能力合并
                permission = entity.getJSONObject(sourceType);

            if(permission.containsKey(sourceName))
                dataRange=permission.getJSONArray(sourceName);

            dataRange.add(dataRangeName);
            permission.put(sourceName,dataRange);
            entity.put(sourceType, permission);
            permission_entity.put(entityName, entity);
        }
        return permission_entity;
    }

    /**
     * 设置用户组织相关信息
     * @param user
     */
    private void setUserOrgInfo(AuthenticationUser user) {

        Map<String, Set<String>> orgInfo=ouFeignClient.getOUMapsByUserId(user.getUserid());
        if(orgInfo==null)
            orgInfo=new HashMap<>();
            //throw new RuntimeException(String.format("获取用户信息失败，请检查用户中心[IBZOU]中是否存在[%s]用户!",user.getLoginname()));

        user.setOrgInfo(orgInfo);
    }


}
