package com.diagbot.facade;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.diagbot.client.UserServiceClient;
import com.diagbot.dto.LantoneProductDTO;
import com.diagbot.dto.LantoneProductOrgDTO;
import com.diagbot.dto.OpendProductDTO;
import com.diagbot.dto.ProductLineDTO;
import com.diagbot.dto.RenewalsInfosDTO;
import com.diagbot.dto.RespDTO;
import com.diagbot.dto.UserOrgDTO;
import com.diagbot.entity.LantoneProduct;
import com.diagbot.entity.OpenedProducts;
import com.diagbot.entity.OpenedProductsIndex;
import com.diagbot.entity.OrderDetailsIndex;
import com.diagbot.entity.ServiceInfo;
import com.diagbot.entity.User;
import com.diagbot.entity.UserRenewals;
import com.diagbot.entity.wrapper.OpendProductWrapper;
import com.diagbot.entity.wrapper.ServiceInfoWrapper;
import com.diagbot.entity.wrapper.UserRenewalsWrapper;
import com.diagbot.enums.AccessTypeEnum;
import com.diagbot.enums.AuditStatusEnum;
import com.diagbot.enums.CancelRenewalsEnum;
import com.diagbot.enums.ChargeTypeEnum;
import com.diagbot.enums.IsDeleteEnum;
import com.diagbot.enums.ProductAuditEnum;
import com.diagbot.enums.RenewalsEnum;
import com.diagbot.enums.ServiceTypeEnum;
import com.diagbot.enums.StatusEnum;
import com.diagbot.enums.TrialStatusEnum;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.diagbot.service.impl.LantoneProductServiceImpl;
import com.diagbot.util.BeanUtil;
import com.diagbot.util.DateUtil;
import com.diagbot.util.EntityUtil;
import com.diagbot.util.UserUtils;
import com.diagbot.vo.AddProductsVO;
import com.diagbot.vo.LantoneProductSelectVO;
import com.diagbot.vo.OppendedProductVO;
import com.diagbot.vo.UpdateProductVO;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * @Description:产品业务层
 * @author: wangyu
 * @time: 2018/9/19 15:52
 */
@Component
public class LantoneProductFacade extends LantoneProductServiceImpl {
    @Autowired
    private OpenedProductsFacade openedProductsFacade;
    @Autowired
    private UserServiceClient userServiceClient;
    @Autowired
    private OrderDetailsFacade orderDetailsFacade;
    @Autowired
    private ServiceInfoFacade serviceInfoFacade;
    @Autowired
    private UserRenewalsFacade userRenewalsFacade;
    @Autowired
    private ProductServiceFacade productServiceFacade;

    /**
     * 产品线管理添加产品
     *
     * @param addProductsVO 需要提供的参数（产品名称，产品介绍，产品url，产品计费方式）
     * @return Boolean true
     */
    public Boolean addProducts(AddProductsVO addProductsVO) {
        LantoneProduct lantoneProductInfos = this.selectProductByName(addProductsVO.getName());
        if(lantoneProductInfos != null && addProductsVO.getName().equals(lantoneProductInfos.getName())){
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                    "产品名称重复");
        }
        LantoneProduct lantoneProduct = new LantoneProduct();
        BeanUtil.copyProperties(addProductsVO, lantoneProduct);
        lantoneProduct.setGmtCreate(DateUtil.now());
        lantoneProduct.setCreator(UserUtils.getCurrentPrincipleID());
        if (!save(lantoneProduct)) {
            throw new CommonException(CommonErrorCode.UPDATE_INFO_FAIL,
                    "产品添加失败");
        }
        return true;
    }


    /**
     * 朗通产品线管理修改产品
     *
     * @param updateProductVO 所需参数（产品名称，url，产品描述，接入模式，收费模式，是否试用）
     * @return Boolean true
     */
    public Boolean updateProduct(UpdateProductVO updateProductVO) {
        LantoneProduct lantoneProductInfo = this.selectProductByName(updateProductVO.getName());
        if(null != lantoneProductInfo && updateProductVO.getName().equals(lantoneProductInfo.getName()) && updateProductVO.getId().intValue() != lantoneProductInfo.getId().intValue()){
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                    "产品名称重复");
        }
        LantoneProduct lantoneProduct = this.getById(updateProductVO.getId());
        if(lantoneProduct.getIsDeleted().equals(IsDeleteEnum.Y.getKey())){
            throw new CommonException(CommonErrorCode.NOT_EXISTS,
                    "该产品已删除,请刷新页面");
        }
        BeanUtil.copyProperties(updateProductVO, lantoneProduct);
        lantoneProduct.setModifier(UserUtils.getCurrentPrincipleID());
        lantoneProduct.setGmtModified(DateUtil.now());
        if(null != updateProductVO.getServiceStatus() && updateProductVO.getServiceStatus()==StatusEnum.Disable.getKey()){
            Page page =new Page();
            OpenedProductsIndex openedProductsIndex =new OpenedProductsIndex();
            openedProductsIndex.setProductId(updateProductVO.getId());
            openedProductsIndex.setServiceStatus(StatusEnum.Enable.getKey());
            if(openedProductsFacade.getByProductId(page,openedProductsIndex).getRecords().size()>0){
                throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                        "用户正在使用中，停用失败");
            }
        }
        if (!updateById(lantoneProduct)) {
            throw new CommonException(CommonErrorCode.UPDATE_INFO_FAIL,
                    "产品修改失败");
        }
        return true;
    }

    /**
     * 朗通产品线管理停用启用产品
     *
     * @param updateProductVO 所需参数（产品id，停用状态）
     * @return Boolean true
     */
    public Boolean stopProduct(UpdateProductVO updateProductVO) {
        LantoneProduct lantoneProduct = this.getById(updateProductVO.getId());
        if(lantoneProduct.getIsDeleted().equals(IsDeleteEnum.Y.getKey())){
            throw new CommonException(CommonErrorCode.NOT_EXISTS,
                    "该产品已删除,请刷新页面");
        }
        if(updateProductVO.getServiceStatus().intValue() == lantoneProduct.getServiceStatus().intValue() && updateProductVO.getServiceStatus().intValue() == StatusEnum.Enable.getKey()){
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                    "该产品已启用，启用失败");
        }
        if(updateProductVO.getServiceStatus().intValue() == lantoneProduct.getServiceStatus().intValue() && updateProductVO.getServiceStatus().intValue() == StatusEnum.Disable.getKey()){
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                    "该产品已停用，停用失败");
        }
        BeanUtil.copyProperties(updateProductVO, lantoneProduct);
        lantoneProduct.setModifier(UserUtils.getCurrentPrincipleID());
        lantoneProduct.setGmtModified(DateUtil.now());
        if(updateProductVO.getServiceStatus().intValue() == StatusEnum.Disable.getKey()){
            Page page =new Page();
            OpenedProductsIndex openedProductsIndex =new OpenedProductsIndex();
            openedProductsIndex.setProductId(updateProductVO.getId());
            openedProductsIndex.setServiceStatus(StatusEnum.Enable.getKey());
            if(openedProductsFacade.getByProductId(page,openedProductsIndex).getRecords().size() > 0){
                throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                        "用户正在使用中，停用失败");
            }
            OrderDetailsIndex orderDetailsIndex =new OrderDetailsIndex();
            orderDetailsIndex.setProductId(updateProductVO.getId());
            orderDetailsIndex.setAuditStatus(AuditStatusEnum.NotAudit.getKey());
            if(orderDetailsFacade.seleAllOrderDetials(orderDetailsIndex).size() > 0){
                throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                        "该产品无法停用，请先处理申请信息");
            }
            UserRenewalsWrapper renewalsInfosDTO =new UserRenewalsWrapper();
            renewalsInfosDTO.setProductId(updateProductVO.getId());
            renewalsInfosDTO.setRenewalsStatus(RenewalsEnum.NOT_RENEWALS.getKey());
            List<RenewalsInfosDTO> list =  userRenewalsFacade.selectUserRenewals(page,renewalsInfosDTO).getRecords();
            UserRenewals userRenewals = new UserRenewals();
            userRenewals.setRenewalsStatus(RenewalsEnum.NOT_RENEWALS.getKey());
            userRenewals.setCancelRenewals(CancelRenewalsEnum.NOT_CANCEL.getKey());
            if(list.contains(userRenewals)){
                throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                        "该产品无法停用，请先处理续费申请信息");
            }
        }
        if (!updateById(lantoneProduct)) {
            throw new CommonException(CommonErrorCode.UPDATE_INFO_FAIL,
                    "产品修改失败");
        }
        return true;
    }

    /**
     * 删除产品业务逻辑
     *
     * @param updateProductVO 所需参数（产品id）
     * @return Boolean true
     */
    public Boolean deleteProduct(UpdateProductVO updateProductVO) {
        LantoneProduct lantoneProduct = this.getById(updateProductVO.getId());
        if(lantoneProduct.getIsDeleted().equals(IsDeleteEnum.Y.getKey())){
            throw new CommonException(CommonErrorCode.NOT_EXISTS,
                    "该产品已删除,请刷新页面");
        }
        if(lantoneProduct.getServiceStatus().intValue() == StatusEnum.Enable.getKey()){
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                    "当前产品正在使用中不可删除");
        }
        OpenedProducts openedProducts = new OpenedProducts();
        openedProducts.setProductId(updateProductVO.getId());
        openedProducts.setServiceStatus(StatusEnum.Enable.getKey());
        if (openedProductsFacade.getOpendById(openedProducts).size() != 0) {
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR,
                    "本产品还有用户使用，删除失败");
        }
        lantoneProduct.setModifier(UserUtils.getCurrentPrincipleID());
        lantoneProduct.setGmtModified(DateUtil.now());
        lantoneProduct.setIsDeleted(IsDeleteEnum.Y.getKey());
        if (!updateById(lantoneProduct)) {
            throw new CommonException(CommonErrorCode.UPDATE_INFO_FAIL,
                    "产品删除失败");
        }
        if(!productServiceFacade.deleteByProductId(updateProductVO.getId())){
                throw new CommonException(CommonErrorCode.UPDATE_INFO_FAIL,
                        "产品令牌删除失败");
        }
        return true;
    }

    /**
     * 查询当前用户已开通产品
     *
     * @return 查询当前用户已开通产品
     */
    public List<LantoneProductOrgDTO> opendedProductByCurrentUser() {
        Long userId = Long.parseLong(UserUtils.getCurrentPrincipleID());
        List<LantoneProductOrgDTO> list = this.opendedProductByUserId(userId);
        List<Long> userIdList = new ArrayList<>();
        userIdList.add(userId);
        RespDTO<Map<Long, UserOrgDTO>> mapRespDTO = userServiceClient.getUserAndOrg(userIdList);
        if (mapRespDTO == null || !"0".equals(mapRespDTO.code)) {
            throw new CommonException(CommonErrorCode.RPC_ERROR,
                    "获取用户机构信息失败");
        }

        List<ServiceInfoWrapper> serviceInfoWrapperList = serviceInfoFacade.selectWrapperListByUserId(userId);
        Map<Long, List<ServiceInfoWrapper>> serviceListMap = EntityUtil.makeEntityListMap(serviceInfoWrapperList, "productId");

        QueryWrapper<ServiceInfo> qwServiceInfo = new QueryWrapper();
        qwServiceInfo.eq("user_id", userId).
                eq("type", ServiceTypeEnum.User_Create.getKey()).
                eq("is_deleted", IsDeleteEnum.N.getKey());
        List<ServiceInfo> serviceInfoList = serviceInfoFacade.list(qwServiceInfo);

        for (LantoneProductOrgDTO product : list) {
            product.setOrganizationName(mapRespDTO.data.get(userId).getOrgName());
            String[] accessType = product.getAccessType().split(",|，");
            String[] chargeType = product.getChargeType().split(",|，");
            String[] accessTypeArray = new String[accessType.length];
            String[] chargeTypeArray = new String[chargeType.length];

            // 仅线上模式
            if (accessType.length == 1 && Integer.valueOf(accessType[0]).equals(AccessTypeEnum.Online.getKey())) {
                product.setOnlyOnline(true);
            }

            // 产品是否在有效期内 该产品未在有效服务期内，无法使用
            if (product.getEndTime().before(new Date())) {
                product.setIsExpired(true);
            } else if (product.getStartTime().after(new Date())) {
                product.setUnStarted(true);
            }

            for (int i = 0; i < accessType.length; i++) {
                accessTypeArray[i] = AccessTypeEnum.getName(Integer.parseInt(accessType[i]));
            }
            for (int i = 0; i < chargeType.length; i++) {
                chargeTypeArray[i] = AccessTypeEnum.getName(Integer.parseInt(chargeType[i]));
            }

            product.setAccessTypeArray(accessTypeArray);
            product.setChargeTypeArray(chargeTypeArray);

            List<ServiceInfoWrapper> serviceWrappers = serviceListMap.get(product.getId());
            Map<Long, ServiceInfoWrapper> serviceRelationMap = EntityUtil.makeEntityMap(serviceWrappers, "id");
            if (serviceWrappers != null) {
                List<ServiceInfo> serviceNoRelations = Lists.newArrayList();
                for (ServiceInfo serviceInfo : serviceInfoList) {
                    if (!serviceRelationMap.containsKey(serviceInfo.getId())) {
                        serviceNoRelations.add(serviceInfo);
                    }
                }
                product.setServiceInfos(serviceNoRelations);
            } else {
                product.setServiceInfos(serviceInfoList);
            }
        }
        return list;
    }

    /**
     * 根据用户id查询是否有开通产品
     *
     * @return 根据用户id查询是否有开通产品
     */
    public RespDTO<List<ProductLineDTO>> productLine() {
        List<ProductLineDTO> productLineDTOList = this.productLines();//所有产品
        Long userId = Long.parseLong(UserUtils.getCurrentPrincipleID());
        List<Long> userIdList =new ArrayList<>();
        userIdList.add(userId);
        List<Long> opendId = openedProductsFacade.getOpendCountByUserId(userId);
        List<Long> orderDetailsId = orderDetailsFacade.getOrderDetailsByUser(userId);
        for (ProductLineDTO productLineDTO:productLineDTOList) {
            if(opendId.contains(productLineDTO.getId())){
                productLineDTO.setProductAudit(ProductAuditEnum.Opended.getKey());
            }else if(orderDetailsId.contains(productLineDTO.getId())){
                productLineDTO.setProductAudit(ProductAuditEnum.Audit.getKey());
            }else {
                productLineDTO.setProductAudit(ProductAuditEnum.NotOpend.getKey());
            }
        }
        RespDTO<User> mapRespDTO = userServiceClient.getUserAuthStatus(userId);
        if (mapRespDTO == null || !"0".equals(mapRespDTO.code)) {
            throw new CommonException(CommonErrorCode.RPC_ERROR,
                    "获取用户机构信息失败");
        }
        Map map =new HashMap();
        map.put("userAuStatus",mapRespDTO.data.getAuthStatus());
        List list =new ArrayList();
        list.add(productLineDTOList);
        list.add(map);
        return RespDTO.onSuc(list);
    }

    /**
     * 根据产品id查询当条产品线下所有订单信息
     *
     * @param oppendedProductVO 所需参数（产品id，页数，和每页条数，默认显示10条）
     * @return 当条产品线下所有订单信息
     */
    public IPage<OpendProductDTO> opendedProduct(OppendedProductVO oppendedProductVO) {
        LantoneProduct lantoneProduct = new LantoneProduct();
        lantoneProduct.setId(oppendedProductVO.getProductId());
        LantoneProduct lantoneProducts = this.getById(lantoneProduct.getId());
        if(lantoneProducts.getIsDeleted().equals(IsDeleteEnum.Y.getKey())){
            throw new CommonException(CommonErrorCode.NOT_EXISTS,
                    "该产品已删除,请刷新页面");
        }
        Page page =new Page();
        BeanUtil.copyProperties(oppendedProductVO,page);
        OpenedProductsIndex openedProductsIndex = new OpenedProductsIndex();
        BeanUtil.copyProperties(oppendedProductVO, openedProductsIndex);
        if(oppendedProductVO.getOrgName() != null && oppendedProductVO.getOrgName() != ""){
            RespDTO<List<Long>> rlist = userServiceClient.getUserByOrgName(oppendedProductVO.getOrgName());
            if(rlist.data.size() == 0){
                rlist.data.add(-1L);
            }
            openedProductsIndex.setUserId(rlist.data);
        }else{
            RespDTO<List<User>> userInfiList = userServiceClient.getUserAllInfo();
            if(userInfiList == null || !"0".equals(userInfiList.code) ) {
                throw new CommonException(CommonErrorCode.RPC_ERROR,
                        "获取用户和机构信息失败");
            }
            List<Long> userIds =new ArrayList<>();
            for (User user:userInfiList.data) {
                userIds.add(user.getId());
            }
            openedProductsIndex.setUserId(userIds);
        }
        List<OpendProductDTO> list = openedProductsFacade.getByProductId(page,openedProductsIndex).getRecords();
        List<Long> list1 = new ArrayList<>();
        for (OpendProductDTO opendProducts : list) {
            Long longs = opendProducts.getUserId();
            list1.add(longs);
        }
        RespDTO<Map<Long, UserOrgDTO>> mapRespDTO = userServiceClient.getUserAndOrg(list1);
        if (mapRespDTO == null || !"0".equals(mapRespDTO.code)) {
            throw new CommonException(CommonErrorCode.RPC_ERROR,
                    "获取用户和机构信息失败");
        }
        Map<Long, UserOrgDTO> dataMap = mapRespDTO.data;
        for (OpendProductWrapper bean : list) {
            UserOrgDTO uo = dataMap.get(bean.getUserId());
            if (uo != null) {
                BeanUtil.copyProperties(uo,bean);
            }
        }
        return page;
    }

    /**
     * 用户-分页查询产品信息
     *
     * @param lantoneProductSelectVO 参数
     * @return 产品信息
     */
    public RespDTO<IPage<LantoneProductDTO>> index(LantoneProductSelectVO lantoneProductSelectVO) {
        Page page =new Page();
        BeanUtil.copyProperties(lantoneProductSelectVO,page);
        IPage<LantoneProductDTO> res = this.selectProduct(page, lantoneProductSelectVO.getName());
        String charName = null;
        String acssName = null;
        for (LantoneProductDTO lantoneProductDTO:res.getRecords()) {
            String charNamebc =new String();
            String acssNamebc =new String();
            charName =lantoneProductDTO.getChargeType();
            acssName =lantoneProductDTO.getAccessType();
            lantoneProductDTO.setTrialStatusName(TrialStatusEnum.getName(lantoneProductDTO.getTrialStatus()));
            String[] strs =charName.split(",");
            for (int i = 0; i<strs.length;i++){
                charNamebc  += ChargeTypeEnum.getName(Integer.parseInt(strs[i]))+",";
            }
            String[] strs1 = acssName.split(",");
            for (int j = 0; j<strs1.length;j++){
                acssNamebc += AccessTypeEnum.getName(Integer.parseInt(strs1[j]))+",";
            }
            lantoneProductDTO.setChargeTypeName(charNamebc);
            lantoneProductDTO.setAccessTypeName(acssNamebc);
        }
        return RespDTO.onSuc(res);
    }
}
