package ink.wgink.login.oauth2.server.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.RemoveException;
import ink.wgink.exceptions.SaveException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.login.oauth2.server.dao.IOAuth2ClientDao;
import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientDTO;
import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientSimpleDTO;
import ink.wgink.login.oauth2.server.pojo.pos.OAuth2ClientPO;
import ink.wgink.login.oauth2.server.pojo.vos.OAuth2ClientVO;
import ink.wgink.login.oauth2.server.service.IOAuth2ClientService;
import ink.wgink.module.menu.pojo.vos.MenuVO;
import ink.wgink.module.menu.service.IMenuService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.util.AesUtil;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.map.HashMapUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @ClassName: OauthClientServiceImpl
 * @Description: Oauth客户端
 * @Author: WangGeng
 * @Date: 2019/3/12 11:40 AM
 * @Version: 1.0
 **/
@Service
public class OAuth2ClientServiceImpl extends DefaultBaseService implements IOAuth2ClientService {

    @Autowired
    private IOAuth2ClientDao oauth2ClientDao;
    @Autowired
    private IMenuService menuService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void save(OAuth2ClientVO oauth2ClientVO) throws SaveException {
        oauth2ClientVO.setClientSecret("{bcrypt}" + passwordEncoder.encode(oauth2ClientVO.getClientSecret()));
        Map<String, Object> params = HashMapUtil.beanToMap(oauth2ClientVO);
        setSaveInfo(params);
        oauth2ClientDao.save(params);
    }

    @Override
    public void remove(List<String> ids) throws RemoveException {
        Map<String, Object> params = getHashMap(6);
        params.put("clientIds", ids);
        setUpdateInfo(params);
        oauth2ClientDao.remove(params);
    }

    @Override
    public void update(String clientId, OAuth2ClientVO oauth2ClientVO) throws UpdateException {
        Map<String, Object> params = HashMapUtil.beanToMap(oauth2ClientVO);
        params.put("clientId", clientId);
        setUpdateInfo(params);
        oauth2ClientDao.update(params);
    }


    @Override
    public void updateMenuInit(String clientId, String menuId) throws UpdateException, SaveException, SearchException {
        OAuth2ClientPO oauth2ClientPO = getPO(clientId);
        if (!StringUtils.isBlank(oauth2ClientPO.getMenuId())) {
            throw new UpdateException("菜单已经绑定", true);
        }
        Map<String, Object> params = getHashMap(2);
        if (StringUtils.isBlank(menuId)) {
            LOG.debug("菜单为空，创建菜单：{}", oauth2ClientPO.getClientName());
            MenuVO menuVO = new MenuVO();
            menuVO.setMenuParentId("0");
            menuVO.setMenuName(oauth2ClientPO.getClientName());
            menuVO.setMenuSummary(oauth2ClientPO.getClientName() + "根节点菜单");
            menuVO.setMenuUrl("javascript:void(0);");
            menuVO.setMenuIcon("fa-icon-color-white fa fa-list");
            menuVO.setMenuStatus(0);
            menuVO.setMenuType(1);
            menuVO.setOpenType(1);
            menuVO.setMenuOrder("1");
            String newMenuId = menuService.saveAndReturnId(menuVO);
            LOG.debug("绑定菜单：{}", oauth2ClientPO.getClientName());
            params.put("menuId", newMenuId);
        } else {
            params.put("menuId", menuId);
        }
        params.put("clientId", clientId);
        oauth2ClientDao.updateMenu(params);
    }

    @Override
    public void updateMenuEmpty(String clientId) throws UpdateException {
        Map<String, Object> params = getHashMap(2);
        params.put("clientId", clientId);
        oauth2ClientDao.updateMenu(params);
    }

    @Override
    public List<OAuth2ClientDTO> list(Map<String, Object> params) throws SearchException {
        return oauth2ClientDao.list(params);
    }

    @Override
    public List<OAuth2ClientSimpleDTO> listSimple(Map<String, Object> params) throws SearchException {
        return oauth2ClientDao.listSimple(params);
    }

    @Override
    public List<OAuth2ClientSimpleDTO> listSimple() {
        Map<String, Object> params = getHashMap(0);
        return listSimple(params);
    }

    @Override
    public List<OAuth2ClientSimpleDTO> listSimpleByEnvironment(String environment) {
        Map<String, Object> params = getHashMap(2);
        params.put("environment", environment);
        return listSimple(params);
    }

    @Override
    public List<OAuth2ClientSimpleDTO> listSimpleByMenuIds(List<String> menuIds) {
        Map<String, Object> params = getHashMap(2);
        params.put("menuIds", menuIds);
        return listSimple(params);
    }

    @Override
    public List<OAuth2ClientSimpleDTO> listSimpleByMenuIdsAndEnvironment(List<String> menuIds, String environment) {
        Map<String, Object> params = getHashMap(2);
        params.put("menuIds", menuIds);
        params.put("environment", environment);
        return listSimple(params);
    }

    @Override
    public SuccessResultList<List<OAuth2ClientDTO>> listPage(ListPage page) throws SearchException {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<OAuth2ClientDTO> oauthClientDTOs = list(page.getParams());
        PageInfo<OAuth2ClientDTO> pageInfo = new PageInfo<>(oauthClientDTOs);
        return new SuccessResultList<>(oauthClientDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public OAuth2ClientDTO get(Map<String, Object> params) throws Exception {
        OAuth2ClientDTO oauthClientDTO = oauth2ClientDao.get(params);
        oauthClientDTO.setClientSecret(Base64.encodeBase64String(AesUtil.aesEncoder(OAUTH_CLIENT_RULE, oauthClientDTO.getClientId()).getBytes("UTF-8")));
        return oauthClientDTO;
    }

    @Override
    public OAuth2ClientDTO get(String clientId) throws Exception {
        Map<String, Object> params = getHashMap(2);
        params.put("clientId", clientId);
        return get(params);
    }

    @Override
    public OAuth2ClientPO getPO(Map<String, Object> params) {
        return oauth2ClientDao.getPO(params);
    }

    @Override
    public OAuth2ClientPO getPO(String clientId) throws SearchException {
        Map<String, Object> params = getHashMap(2);
        params.put("clientId", clientId);
        return getPO(params);
    }

    @Override
    public OAuth2ClientDTO getInit() throws Exception {
        OAuth2ClientDTO oauthClientDTO = new OAuth2ClientDTO();
        String clientId = UUIDUtil.get32UUID();
        String clientSecret = Base64.encodeBase64String(AesUtil.aesEncoder(OAUTH_CLIENT_RULE, clientId).getBytes("UTF-8"));
        oauthClientDTO.setClientId(clientId);
        oauthClientDTO.setClientSecret(clientSecret);
        oauthClientDTO.setAccessTokenValidity(7200);
        oauthClientDTO.setRefreshTokenValidity(7200);
        return oauthClientDTO;
    }


    @Override
    public Integer count(Map<String, Object> params) throws SearchException {
        Integer oauthClientCount = oauth2ClientDao.count(params);
        return oauthClientCount == null ? 0 : oauthClientCount;
    }


}
