package com.diagbot.facade;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.diagbot.dto.ProductServiceDTO;
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.ProductServiceWrapper;
import com.diagbot.enums.TokenTypeEnum;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.diagbot.service.impl.ProductServiceServiceImpl;
import com.diagbot.util.DateUtil;
import com.diagbot.util.EntityUtil;
import com.diagbot.util.GuidUtil;
import com.diagbot.util.UserUtils;
import com.diagbot.vo.ProductServiceSaveVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * @Description:产品与用户端关联业务层
 * @author: zhaops
 * @time: 2018/9/18 16:33
 */
@Component
public class ProductServiceFacade extends ProductServiceServiceImpl {
    @Autowired
    private ServiceTokenFacade serviceTokenFacade;
    @Autowired
    private ServiceInfoFacade serviceInfoFacade;
    @Autowired
    private LantoneProductFacade lantoneProductFacade;
    @Autowired
    private OpenedProductsFacade openedProductsFacade;

    /**
     * @Description:建立产品服务端关联并生成令牌
     * @author: zhaops
     * @time: 2018/9/18 16:33
     */
    public ProductServiceDTO genProductService(ProductServiceSaveVO productServiceSaveVO) {
        ProductServiceDTO productServiceDTO = new ProductServiceDTO();
        Calendar calendar = Calendar.getInstance();
        Long userId = Long.parseLong(UserUtils.getCurrentPrincipleID());
        LantoneProduct lantoneProduct = lantoneProductFacade.getById(productServiceSaveVO.getProductId());
        if (lantoneProduct == null) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS,
                    "找不到产品【" + lantoneProduct.getName() + "】");
        }
        ServiceInfo serviceInfo = serviceInfoFacade.getById(productServiceSaveVO.getServiceId());
        if (serviceInfo == null) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS,
                    "找不到服务端【" + serviceInfo.getName() + "】");
        } else if (serviceInfo.getUserId() != userId) {
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                    "当前登录用户没有关联服务端【" + serviceInfo.getName() + "】");
        }

        Map<String, Object> map = new HashMap<>();
        map.put("productId", productServiceSaveVO.getProductId());
        map.put("serviceId", productServiceSaveVO.getServiceId());
        ProductService productService = this.findByProductIdAndServiceId(map);
        if (productService == null) {
            productService = new ProductService();
            productService.setProductId(productServiceSaveVO.getProductId());
            productService.setServiceId(productServiceSaveVO.getServiceId());
            productService.setCreator(userId.toString());
            productService.setGmtCreate(new Date());
            this.save(productService);
        } else {
            productService.setModifier(userId.toString());
            productService.setGmtModified(new Date());
            this.updateById(productService);
        }

        // 生成令牌
        // 如果已有令牌，先删除原令牌，再重新生成
        // 试用产品 type=3 需生成7天有效期，重新生成令牌，有效期继承，超出有效期不允许再生成令牌
        ServiceToken old_serviceToken = serviceTokenFacade.getByProductServiceId(productService.getId());
        //删除原有token
        if (old_serviceToken != null) {
            serviceTokenFacade.deleteByProductServiceId(old_serviceToken.getProductServiceId());
        }

        ServiceToken serviceToken = new ServiceToken();
        serviceToken.setCreator(userId.toString());
        serviceToken.setGmtCreate(new Date());
        serviceToken.setProductServiceId(productService.getId());
        serviceToken.setType(productServiceSaveVO.getType());
        serviceToken.setAppKeyId(GuidUtil.App_key());
        serviceToken.setAppKeySecret(GuidUtil.App_screct());
        serviceToken.setStatus(1);
        if (old_serviceToken != null && old_serviceToken.getType().equals(TokenTypeEnum.Trial.getKey())) {
            //如果试用已过期，不允许再生成
            if (calendar.after(old_serviceToken.getExpiringDate())) {
                throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                        "当前试用账号已过期，不允许再生成令牌");
            }
            serviceToken.setStartingDate(old_serviceToken.getStartingDate());
            serviceToken.setExpiringDate(old_serviceToken.getExpiringDate());
        } else if (productServiceSaveVO.getType().equals(TokenTypeEnum.Trial.getKey())) {
            serviceToken.setStartingDate(new Date());
            serviceToken.setExpiringDate(DateUtil.addDay(serviceToken.getStartingDate(), 7));
        }
        serviceTokenFacade.save(serviceToken);
        productServiceDTO.setServiceToken(serviceToken);

        productServiceDTO.setProductService(productService);
        return productServiceDTO;
    }

    /**
     * @Description:删除产品服务端关联，级联删除令牌
     * @author: zhaops
     * @time: 2018/9/18 16:33
     */
    public Boolean deleteProductService(ProductServiceSaveVO productServiceSaveVO) {
        Map<String, Object> map = new HashMap<>();
        map.put("productId", productServiceSaveVO.getProductId());
        map.put("serviceId", productServiceSaveVO.getServiceId());
        ProductService productService = this.findByProductIdAndServiceId(map);
        if (productService == null) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS,
                    "找不到产品服务端");
        }
        //删除关联令牌
        serviceTokenFacade.deleteByProductServiceId(productService.getId());
        //删除产品服务端
        this.delById(productService.getId());
        return true;
    }

    /**
     * @Description:获取当前用户产品服务关联列表
     * @author: zhaops
     * @time: 2018/9/18 16:33
     */
    public IPage<ProductServiceWrapper> selectProductServiceByCurrentUserPage(Page<ProductServiceWrapper> page) {
        Long userId = Long.parseLong(UserUtils.getCurrentPrincipleID());
        //当前登录用户服务端列表
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("is_deleted", "N");
        columnMap.put("user_id", userId);
        List<ServiceInfo> serviceInfoList = (List) serviceInfoFacade.listByMap(columnMap);
        Map<Long, ServiceInfo> serviceData = EntityUtil.makeEntityMap(serviceInfoList, "id");
        //服务令牌列表
        columnMap.clear();
        columnMap.put("is_deleted", "N");
        List<ServiceToken> serviceTokenList = (List) serviceTokenFacade.listByMap(columnMap);
        Map<Long, ServiceToken> tokenData = EntityUtil.makeEntityMap(serviceTokenList, "productServiceId");
        //产品列表
        columnMap.clear();
        columnMap.put("is_deleted", "N");
        List<LantoneProduct> lantoneProductList = (List) lantoneProductFacade.listByMap(columnMap);
        Map<Long, LantoneProduct> lantoneProductData = EntityUtil.makeEntityMap(lantoneProductList, "id");
        //当前用户开通的产品列表
        columnMap.clear();
        columnMap.put("is_deleted", "N");
        columnMap.put("user_id", userId);
        List<OpenedProducts> openedProductsList = (List) openedProductsFacade.listByMap(columnMap);
        Map<Long, OpenedProducts> openedProductData = EntityUtil.makeEntityMap(openedProductsList, "productId");

        ProductServiceWrapper productServiceVO = new ProductServiceWrapper();
        productServiceVO.setUserId(userId);
        IPage<ProductServiceWrapper> psPage = this.selectProductServiceByUserIdPage(page, productServiceVO);
        List<ProductServiceWrapper> psList = psPage.getRecords();
        for (ProductServiceWrapper productService : psList) {
            productService.setLantoneProduct(lantoneProductData.get(productService.getProductId()));
            productService.setOpenedProducts(openedProductData.get(productService.getProductId()));
            productService.setServiceInfo(serviceData.get(productService.getServiceId()));
            productService.setServiceToken(tokenData.get(productService.getId()));
        }
        psPage.setRecords(psList);
        return psPage;
    }
}
