package com.zfire.mall.manager.logic.manage.product.category;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zfire.mall.manager.bean.admin.AdminUserCom;
import com.zfire.mall.manager.bean.manage.product.category.ProductCategoryBean;
import com.zfire.mall.manager.bean.manage.product.category.ProductCategoryRelaBean;
import com.zfire.mall.manager.constant.Constant;
import com.zfire.mall.manager.exception.RemoteServiceException;
import com.zfire.mall.manager.logic.common.CommonLogic;
import com.zfire.mall.manager.plus.entity.KingDeeCategory;
import com.zfire.mall.manager.plus.entity.ProductCategory;
import com.zfire.mall.manager.plus.entity.ProductCategoryRela;
import com.zfire.mall.manager.plus.service.AdminCompanyService;
import com.zfire.mall.manager.plus.service.KingDeeCategoryService;
import com.zfire.mall.manager.plus.service.ProductCategoryRelaService;
import com.zfire.mall.manager.plus.service.ProductCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ProductCategoryLogic {

    @Resource
    CommonLogic commonLogic;
    @Resource
    ProductCategoryService productCategoryService;
    @Resource
    ProductCategoryRelaService productCategoryRelaService;
    @Resource
    KingDeeCategoryService kingDeeCategoryService;
    @Resource
    RedisLockRegistry redisLockRegistry;

    @Transactional(rollbackFor = Exception.class)
    public Object add(ProductCategoryBean productCategoryBean) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        productCategoryBean.setProductCategoryId(null);

        // 检查类别编码和名称唯一性
        this.checkUniqueProductCategory(productCategoryBean, adminUser);

        // 保存类别 用编码当id
        ProductCategory productCategory = new ProductCategory();
        productCategory.setAdminCompanyId(adminUser.getAdminCompanyId())
                .setProductCategoryNumber(productCategoryBean.getProductCategoryNumber().trim())
                .setProductCategoryName(productCategoryBean.getProductCategoryName().trim())
                .setProductCategoryId(productCategoryBean.getProductCategoryNumber())
                .setCreateName(adminUser.getNickName())
                .setUpdateName(adminUser.getNickName())
                .insert();

        return productCategory.getProductCategoryId();
    }

    private void checkUniqueProductCategory(ProductCategoryBean productCategoryBean, AdminUserCom adminUser) {
        String productCategoryNumber = productCategoryBean.getProductCategoryNumber().trim();
        String productCategoryName = productCategoryBean.getProductCategoryName().trim();

        ProductCategory entity = productCategoryService.lambdaQuery()
                .in(CollectionUtils.isNotEmpty(adminUser.getAdminCompanyIds()), ProductCategory::getAdminCompanyId, adminUser.getAdminCompanyId())
                .ne(StringUtils.isNotEmpty(productCategoryBean.getProductCategoryId()), ProductCategory::getProductCategoryId, productCategoryBean.getProductCategoryId())
                .and(productCategoryLambdaQueryWrapper ->
                        productCategoryLambdaQueryWrapper.eq(ProductCategory::getProductCategoryNumber, productCategoryBean.getProductCategoryNumber().trim())
                                .or()
                                .eq(ProductCategory::getProductCategoryName, productCategoryBean.getProductCategoryName().trim()))
                .one();

        if (Objects.nonNull(entity)) {
            if (entity.getProductCategoryName().equals(productCategoryName)) {
                throw new RemoteServiceException(productCategoryName + "：类别名称已存在");
            }
            throw new RemoteServiceException(productCategoryNumber + "：类别编码已存在");
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public void edit(ProductCategoryBean productCategoryBean) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        this.checkUniqueProductCategory(productCategoryBean, adminUser);

        // 修改品类 不可更改编码
        productCategoryService.update(new ProductCategory(), new LambdaUpdateWrapper<ProductCategory>()
                .set(ProductCategory::getProductCategoryNumber, productCategoryBean.getProductCategoryNumber().trim())
                .set(ProductCategory::getProductCategoryName, productCategoryBean.getProductCategoryName().trim())
                .set(ProductCategory::getProductCategoryNumber,null)
                .set(ProductCategory::getUpdateName, adminUser.getNickName())
                .eq(ProductCategory::getAdminCompanyId, adminUser.getAdminCompanyId())
                .eq(ProductCategory::getProductCategoryId, productCategoryBean.getProductCategoryId()));
    }

    public List<ProductCategory> allList(String productCategoryNumber, String productCategoryName) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        return productCategoryService.lambdaQuery()
                .in(CollectionUtils.isNotEmpty(adminUser.getAdminCompanyIds()), ProductCategory::getAdminCompanyId, adminUser.getAdminCompanyIds())
                .like(StringUtils.isNotEmpty(productCategoryNumber), ProductCategory::getProductCategoryNumber, productCategoryNumber)
                .like(StringUtils.isNotEmpty(productCategoryName), ProductCategory::getProductCategoryName, productCategoryName)
                .orderByDesc(ProductCategory::getCreateTime)
                .list();
    }

    public ProductCategory detail(String id) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        return productCategoryService.lambdaQuery()
                .in(CollectionUtils.isNotEmpty(adminUser.getAdminCompanyIds()), ProductCategory::getAdminCompanyId, adminUser.getAdminCompanyIds())
                .eq(ProductCategory::getProductCategoryId, id)
                .one();
    }



    public List<ProductCategoryRelaBean> subList(String id) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<ProductCategoryRela> productCategoryRelas = productCategoryRelaService.lambdaQuery()
                .eq(StringUtils.isNotBlank(adminUser.getAdminCompanyId()), ProductCategoryRela::getAdminCompanyId, adminUser.getAdminCompanyId())
                .eq(ProductCategoryRela::getProductCategoryId, id)
                .list();

        if (productCategoryRelas.size() == 0) {
            return new ArrayList<>();
        }

        List<KingDeeCategory> kingDeeCategories = kingDeeCategoryService.lambdaQuery()
                .in(KingDeeCategory::getId, productCategoryRelas.stream()
                        .map(ProductCategoryRela::getKingDeeCategoryId)
                        .collect(Collectors.toList()))
                .list();

        Map<String, KingDeeCategory> deeCategoryMap = kingDeeCategories.stream()
                .collect(Collectors.toMap(KingDeeCategory::getId, Function.identity()));

        return productCategoryRelas.stream()
                .map(productCategoryRela -> {
                    KingDeeCategory kingDeeCategory = deeCategoryMap.get(productCategoryRela.getKingDeeCategoryId());
                    ProductCategoryRelaBean bean = new ProductCategoryRelaBean();
                    BeanUtils.copyProperties(productCategoryRela, bean);
                    bean.setKingDeeCategoryName(kingDeeCategory.getName());
                    bean.setKingDeeCategoryNumber(kingDeeCategory.getNumber());
                    return bean;
                }).collect(Collectors.toList());
    }


    public void delSub(List<String> ids) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<String> collect = ids.stream().distinct().collect(Collectors.toList());
        productCategoryRelaService.lambdaUpdate()
                .eq(ProductCategoryRela::getAdminCompanyId, adminUser.getAdminCompanyId())
                .in(ProductCategoryRela::getId, collect)
                .remove();
    }

    public List<KingDeeCategory> kingDeeCategoryList() {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<KingDeeCategory> kingDeeCategories = kingDeeCategoryService
                .list();

        List<ProductCategoryRela> productCategoryRelas = productCategoryRelaService.lambdaQuery()
                .eq(ProductCategoryRela::getAdminCompanyId, adminUser.getAdminCompanyId())
                .list();
        Map<String, ProductCategoryRela> categoryRelaMap = productCategoryRelas.stream()
                .collect(Collectors.toMap(ProductCategoryRela::getKingDeeCategoryId, Function.identity(), (key1, key2) -> key2));

        return kingDeeCategories.stream()
                .filter(kingDeeCategory -> {
                    ProductCategoryRela productCategoryRela = categoryRelaMap.get(kingDeeCategory.getId());
                    return Objects.isNull(productCategoryRela);
                }).collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    public void addSub(ProductCategoryBean productCategoryBean) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.PRODUCT_SUB_CATEGORY + adminUser.getAdminUserId());
        try {
            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
                // 清掉当前品类的小类
                productCategoryRelaService.lambdaUpdate()
                        .eq(ProductCategoryRela::getAdminCompanyId, adminUser.getAdminCompanyId())
                        .eq(ProductCategoryRela::getProductCategoryId, productCategoryBean.getProductCategoryId())
                        .remove();
                // 获取当前企业下的所有已关联小类
                List<ProductCategoryRela> productCategoryRelas = productCategoryRelaService.lambdaQuery()
                        .eq(ProductCategoryRela::getAdminCompanyId, adminUser.getAdminCompanyId())
                        .list();

                // 与请求的小类比较
                Map<String, ProductCategoryRela> relaMap = productCategoryRelas.stream()
                        .collect(Collectors.toMap(ProductCategoryRela::getKingDeeCategoryId, Function.identity(), (key1, key2) -> key2));

                List<ProductCategoryRelaBean> productCategoryRelaBeans = productCategoryBean.getItems().stream()
                        .filter(productCategoryRelaBean -> {
                            ProductCategoryRela productCategoryRela = relaMap.get(productCategoryRelaBean.getKingDeeCategoryId());
                            return Objects.nonNull(productCategoryRela);
                        })
                        .collect(Collectors.toList());

                if (productCategoryRelaBeans.size() > 0) {
                    // 已有关联小类不能添加
                    ProductCategoryRelaBean bean = productCategoryRelaBeans.get(0);

                    throw new RemoteServiceException(bean.getKingDeeCategoryName() + "：已经存在关联，请检查");
                }

                // 保存小类
                productCategoryRelaService.saveBatch(productCategoryBean.getItems().stream().map(productCategoryRelaBean -> {
                    ProductCategoryRela productCategoryRela = new ProductCategoryRela();
                    productCategoryRela.setProductCategoryId(productCategoryBean.getProductCategoryId())
                            .setKingDeeCategoryId(productCategoryRelaBean.getKingDeeCategoryId())
                            .setAdminCompanyId(adminUser.getAdminCompanyId());
                    return productCategoryRela;
                }).collect(Collectors.toList()));
            }
        }catch(Exception e){
            log.error("【产品品类小类添加】失败", e);
            throw e;
        }finally {
            obtain.unlock();
        }
    }

    public void del(List<String> ids) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<String> collect = ids.stream().distinct().collect(Collectors.toList());
        productCategoryService.lambdaUpdate()
                .eq(ProductCategory::getAdminCompanyId, adminUser.getAdminCompanyId())
                .in(ProductCategory::getProductCategoryId, collect)
                .remove();
    }

    /**
     *  查询所有绑定了品类的物料类型id
     */
    public List<String> queryCategoryIds(){
        List<ProductCategoryRela> list = productCategoryRelaService.list();
        return list.stream().map(ProductCategoryRela::getKingDeeCategoryId).collect(Collectors.toList());
    }


    public List<KingDeeCategory> kingDeeCategory() {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<KingDeeCategory> kingDeeCategories = kingDeeCategoryService
                .list();

        return kingDeeCategories;
    }
}
