package com.cf.imes.module.system.service.application;

import com.cf.imes.framework.common.exception.ServerException;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.monitor.TracerUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.common.util.servlet.ServletUtils;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.module.system.api.logger.dto.LoginLogCreateReqDTO;
import com.cf.imes.module.system.controller.admin.application.vo.application.ApplicationPageReqVO;
import com.cf.imes.module.system.controller.admin.application.vo.application.ApplicationRespVO;
import com.cf.imes.module.system.controller.admin.application.vo.application.ApplicationSaveReqVO;
import com.cf.imes.module.system.controller.admin.application.vo.auth.ApplicationLoginRespVO;
import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginRespVO;
import com.cf.imes.module.system.convert.auth.AuthConvert;
import com.cf.imes.module.system.dal.dataobject.application.ApplicationDO;
import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.dal.mysql.application.ApplicationMapper;
import com.cf.imes.module.system.enums.ErrorCodeConstants;
import com.cf.imes.module.system.enums.logger.LoginLogTypeEnum;
import com.cf.imes.module.system.enums.logger.LoginResultEnum;
import com.cf.imes.module.system.enums.oauth2.OAuth2ClientConstants;
import com.cf.imes.module.system.service.oauth2.OAuth2TokenService;
import com.cf.imes.module.system.util.rsa.AsymmetricAlgorithmUtil;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.APPLICATION_NOT_EXISTS;

/**
 * 应用信息表 application Service 实现类
 *
 * @author 晨丰科技
 */
@Service
@Validated
public class ApplicationServiceImpl implements ApplicationService{

    @Resource
    private ApplicationMapper applicationMapper;

    @Resource
    private OAuth2TokenService oauth2TokenService;

    @Override
    public Integer createApplication(ApplicationSaveReqVO createReqVO) {
        // 插入
        LinkedList<String> priKeyAndPubKey = AsymmetricAlgorithmUtil.getPriKeyAndPubKey();
        String privateKey = priKeyAndPubKey.get(0);
        String publicKey = priKeyAndPubKey.get(1);
        String appKey = AsymmetricAlgorithmUtil.encryptByPublic(createReqVO.getAppId(), publicKey);
//        公钥加密，私钥解密
        ApplicationDO applicationDO = BeanUtils.toBean(createReqVO, ApplicationDO.class)
                .setAppKey(appKey).setAppSecret(privateKey);
        applicationMapper.insert(applicationDO);
        // 返回
        return applicationDO.getId();
    }

    @Override
    public void updateApplication(ApplicationSaveReqVO updateReqVO) {
        // 校验存在
        validateApplicationExists(updateReqVO.getId());
        // 更新
        ApplicationDO updateObj = BeanUtils.toBean(updateReqVO, ApplicationDO.class);
        applicationMapper.updateById(updateObj);
    }

    @Override
    public void deleteApplication(Long id) {
        // 校验存在
        validateApplicationExists(id);
        // 删除
        applicationMapper.deleteById(id);
    }

    private void validateApplicationExists(Long id) {
        if (applicationMapper.selectById(id) == null) {
            throw exception(APPLICATION_NOT_EXISTS);
        }
    }

    @Override
    public ApplicationDO getApplication(Long id) {
        return applicationMapper.selectById(id);
    }

    @Override
    public PageResult<ApplicationDO> getApplicationPage(ApplicationPageReqVO pageReqVO) {
        return applicationMapper.selectPage(pageReqVO);
    }

    @Override
    public ApplicationLoginRespVO loginApplication(ApplicationRespVO reqVO) {
        ApplicationDO app = applicationMapper.selectByAppId(reqVO.getAppId());
        if (Objects.isNull(app)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.APPLICATION_NOT_EXISTS);
        }
//        公钥加密，私钥解密
        String appId = AsymmetricAlgorithmUtil.encryptByPublic(reqVO.getAppKey(), app.getAppSecret());
        if (!appId.equals(app.getAppId())) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.APPLICATION_LOGIN_USER_DISABLED);
        }
        // 创建 Token 令牌，记录登录日志
        return BeanUtils.toBean(createTokenAfterLoginSuccess(app.getId(), app.getAppId(), LoginLogTypeEnum.LOGIN_USERNAME), ApplicationLoginRespVO.class).setAppId(app.getId());
    }

    @Override
    public ApplicationDO getApplicationByOrganId(Long organId) {
        return applicationMapper.selectByOrganId(organId);
    }

    private AuthLoginRespVO createTokenAfterLoginSuccess(Integer userId, String username, LoginLogTypeEnum logType) {
//        Long organId = OrganContextHolder.getOrganId();
//        OrganizationDO organ = organService.getOrgan(organId);
//        if(Objects.isNull(organ)) {
//            throw new ServerException(10023,"组织不存在");
//        }
        // 创建访问令牌
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(
                1L,
                null,
                OAuth2ClientConstants.CLIENT_ID_DEFAULT,
                null,
                null,
                null,
                null,
                null,
                null,
                null
                );
        // 构建返回结果
        return AuthConvert.INSTANCE.convert(accessTokenDO);
    }

}
