package com.diagbot.facade;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.diagbot.dto.HasPermissionDTO;
import com.diagbot.dto.RespDTO;
import com.diagbot.entity.LantoneProduct;
import com.diagbot.entity.OpenedProducts;
import com.diagbot.entity.ProductService;
import com.diagbot.entity.ServiceInfo;
import com.diagbot.entity.ServiceToken;
import com.diagbot.entity.wrapper.ServiceTokenWrapper;
import com.diagbot.enums.IsDeleteEnum;
import com.diagbot.enums.StatusEnum;
import com.diagbot.enums.TokenTypeEnum;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.diagbot.service.impl.ServiceTokenServiceImpl;
import com.diagbot.util.BeanUtil;
import com.diagbot.util.ListUtil;
import com.diagbot.util.UserUtils;
import com.diagbot.vo.ServiceTokenVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 用户端token业务层
 * @author: zhaops
 * @time: 2018/9/18 16:31
 */
@Component
public class ServiceTokenFacade extends ServiceTokenServiceImpl {


    @Autowired
    ProductServiceFacade productServiceFacade;
    @Autowired
    OpenedProductsFacade openedProductsFacade;
    @Autowired
    ServiceInfoFacade serviceInfoFacade;
    @Autowired
    LantoneProductFacade lantoneProductFacade;


    /**
     * 获取资源的url
     *
     * @param serviceTokenVo 参数
     * @return 是否有权限
     */
    public RespDTO<HasPermissionDTO> hasPermission(ServiceTokenVo serviceTokenVo) {
        HasPermissionDTO hasPermissionDTO = new HasPermissionDTO();
        String appkey = serviceTokenVo.getAppkey();
        String secret = serviceTokenVo.getSecret();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("appkey", appkey);
        paramMap.put("secret", secret);
        paramMap.put("productId", serviceTokenVo.getProductId());

        //获取用户的id
        List<ServiceTokenWrapper> serviceTokenWrapperList = this.getByAppkeyAndSecretAndProductId(paramMap);

        if (ListUtil.isEmpty(serviceTokenWrapperList)) {
            throw new CommonException(CommonErrorCode.APPKEY_ERROR);
        }
        ServiceTokenWrapper st = serviceTokenWrapperList.get(0);
        if (StatusEnum.Disable.getKey() == st.getServiceStatus()) {
            throw new CommonException(CommonErrorCode.PRODUCT_STOP_ERROR);
        }
        if (TokenTypeEnum.Trial.getKey() == st.getType()) {
            Date date = new Date();
            if (st.getExpiringDate().getTime() < date.getTime()) {
                throw new CommonException(CommonErrorCode.OVERDUE_ERROR);
            }
        } else {
            QueryWrapper<OpenedProducts> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey());
            queryWrapper.eq("user_id", st.getUserId());
            queryWrapper.eq("product_id", st.getProductId());
            OpenedProducts op = openedProductsFacade.getOne(queryWrapper);
            if (op == null) {
                throw new CommonException(CommonErrorCode.NOPERMISSION_ERROR);
            }
            Date date = new Date();
            if (!(StatusEnum.Enable.getKey() == op.getServiceStatus())) {
                throw new CommonException(CommonErrorCode.SERVICE_STOP_ERROR);
            }
            if (op.getStartTime().getTime() > date.getTime()) {
                throw new CommonException(CommonErrorCode.NOTVALID_ERROR);
            }
            if (op.getEndTime().getTime() < date.getTime()) {
                throw new CommonException(CommonErrorCode.EXPIRE_ERROR);
            }
        }
        hasPermissionDTO.setHasPermission(true);
        //获取用户的id
        if (st.getUserId() != null) {
            hasPermissionDTO.setUserId(st.getUserId().toString());
        }
        return RespDTO.onSuc(hasPermissionDTO);
    }

    /**
     * 根据产品服务关联id获取令牌
     *
     * @param productServiceId
     * @return
     */
    public ServiceToken getByProductServiceId(Long productServiceId) {
        QueryWrapper<ServiceToken> qw = new QueryWrapper<>();
        qw.eq("product_service_id", productServiceId);
        return this.selectOneRecord(qw);
    }

    /**
     * 根据产品服务关联id获取令牌（包含产品和服务端信息）
     *
     * @param productServiceId
     * @return
     */
    public ServiceTokenWrapper getWrapperByProductServiceId(Long productServiceId) {

        checkCurrentUser(productServiceId);
        QueryWrapper<ServiceToken> qw = new QueryWrapper<>();
        qw.eq("product_service_id", productServiceId).
                eq("type", TokenTypeEnum.Manual.getKey());
        ServiceToken serviceToken = this.selectOneRecord(qw);
        ServiceTokenWrapper serviceTokenWrapper = new ServiceTokenWrapper();
        BeanUtil.copyProperties(serviceToken, serviceTokenWrapper);

        ProductService productService = productServiceFacade.getById(productServiceId);
        ServiceInfo serviceInfo = serviceInfoFacade.getById(productService.getServiceId());
        LantoneProduct lantoneProduct = lantoneProductFacade.getById(productService.getProductId());
        if (lantoneProduct == null || lantoneProduct.getIsDeleted().equals(IsDeleteEnum.Y.getKey())) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS, "产品不存在");
        }

        serviceTokenWrapper.setServiceName(serviceInfo.getName());
        serviceTokenWrapper.setProductName(lantoneProduct.getName());

        return serviceTokenWrapper;
    }

    /**
     * 根据产品服务关联id删除令牌
     *
     * @param productServiceId
     * @return
     */
    public Integer deleteByProductServiceId(Long productServiceId) {
        checkCurrentUser(productServiceId);
        UpdateWrapper<ServiceToken> uw = new UpdateWrapper<>();
        uw.eq("product_service_id", productServiceId).
                eq("type", TokenTypeEnum.Manual.getKey());
        ServiceToken serviceToken = new ServiceToken();
        serviceToken.setIsDeleted(IsDeleteEnum.Y.getKey());
        return this.updateRecord(serviceToken, uw);
    }

    /**
     * 根据id批量删除令牌
     *
     * @param ids
     * @return
     */
    public Boolean deleteByIds(Long[] ids) {
        QueryWrapper<ServiceToken> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", ids);
        List<ServiceToken> serviceTokenList = this.list(queryWrapper);
        for (ServiceToken serviceToken : serviceTokenList) {
            serviceToken.setIsDeleted(IsDeleteEnum.Y.getKey());
        }
        return this.updateBatchById(serviceTokenList);
    }

    /**
     * 根据条件批量删除令牌
     *
     * @param queryWrapper
     * @return
     */
    public Boolean deleteByWrapper(QueryWrapper<ServiceToken> queryWrapper) {
        List<ServiceToken> serviceTokenList = this.list(queryWrapper);
        for (ServiceToken serviceToken : serviceTokenList) {
            serviceToken.setIsDeleted(IsDeleteEnum.Y.getKey());
        }
        return this.updateBatchById(serviceTokenList);
    }

    /**
     * 启用令牌
     *
     * @param productServiceId
     * @return
     */
    public Integer enableToken(Long productServiceId) {
        checkCurrentUser(productServiceId);
        UpdateWrapper<ServiceToken> uw = new UpdateWrapper<>();
        uw.eq("product_service_id", productServiceId).
                eq("type", TokenTypeEnum.Manual.getKey());
        ServiceToken serviceToken = new ServiceToken();
        serviceToken.setStatus(StatusEnum.Enable.getKey());
        return this.updateRecord(serviceToken, uw);
    }

    /**
     * 禁用令牌
     *
     * @param productServiceId
     * @return
     */
    public Integer disableToken(Long productServiceId) {
        checkCurrentUser(productServiceId);
        UpdateWrapper<ServiceToken> uw = new UpdateWrapper<>();
        uw.eq("product_service_id", productServiceId).
                eq("type", TokenTypeEnum.Manual.getKey());
        ServiceToken serviceToken = new ServiceToken();
        serviceToken.setStatus(StatusEnum.Disable.getKey());
        return this.updateRecord(serviceToken, uw);
    }

    /**
     * 校验令牌所属用户是否当前登录用户
     *
     * @param productServiceId
     * @return
     */
    public Boolean checkCurrentUser(Long productServiceId) {
        Long userId = Long.parseLong(UserUtils.getCurrentPrincipleID());
        ProductService productService = productServiceFacade.getById(productServiceId);
        if (productService == null || productService.getIsDeleted().equals(IsDeleteEnum.Y.getKey())) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS, "产品服务端关联不存在");
        }
        ServiceInfo serviceInfo = serviceInfoFacade.getById(productService.getServiceId());
        if (serviceInfo == null || serviceInfo.getIsDeleted().equals(IsDeleteEnum.Y.getKey())) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS, "服务端不存在");
        } else if (serviceInfo.getUserId() != userId) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS, "登录用户与令牌所属用户不一致");
        }
        return true;
    }

    /**
     * 根据条件查询令牌
     *
     * @param map
     * @return
     */
    public ServiceToken getTokenByMap(Map<String, Object> map) {
        QueryWrapper<ServiceToken> queryWrapper = new QueryWrapper<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            queryWrapper.eq(entry.getKey(), entry.getValue());
        }
        return this.getOne(queryWrapper);
    }
}