package com.tofly.qualitycontrol.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tofly.qualitycontrol.common.QualityControlConstant;
import com.tofly.qualitycontrol.entity.CollectionNumber;
import com.tofly.qualitycontrol.entity.CollectionNumberDetail;
import com.tofly.qualitycontrol.exception.QualityControlBusinessException;
import com.tofly.qualitycontrol.mapper.CollectionNumberMapper;
import com.tofly.qualitycontrol.service.ICollectionNumberDetailService;
import com.tofly.qualitycontrol.service.ICollectionNumberService;
import com.tofly.qualitycontrol.vo.CollectionNumberVO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static com.google.common.collect.Lists.newArrayList;
import static com.tofly.qualitycontrol.util.QualityControlUtil.*;

/**
 * @author B
 */
@Service
@RequiredArgsConstructor
public class CollectionNumberServiceImpl extends ServiceImpl<CollectionNumberMapper, CollectionNumber> implements ICollectionNumberService, QualityControlConstant {

    private final ICollectionNumberDetailService collectionNumberDetailService;
    private final StringRedisTemplate template;

    @Override
    public Boolean saveCollectionNumber(CollectionNumber collectionNumber) {
        String collectionNumberKey = "GJ99";
        String collectionTypeRedisKey = null;
        int benNumber = 1;
        if (COLLECTION_TYPE_USER.equals(collectionNumber.getCollectionType())) {
            collectionTypeRedisKey = COLLECTION_TYPE_REDIS_KEY_USER + collectionNumberKey;
        } else if (COLLECTION_TYPE_MANAGE.equals(collectionNumber.getCollectionType())) {
            collectionTypeRedisKey = COLLECTION_TYPE_REDIS_KEY_ADMIN + collectionNumberKey;
            benNumber = 1000001;
        } else {
            return false;
        }
        BoundValueOperations<String, String> ops = template.boundValueOps(collectionTypeRedisKey);
        if (template.hasKey(collectionTypeRedisKey)) {
            ops.increment(1);
        } else {
            CollectionNumber cNumber = getOne(new QueryWrapper<CollectionNumber>().select("Max(COLLECTION_NUMBER) as COLLECTION_NUMBER").lambda().eq(CollectionNumber::getCollectionType, collectionNumber.getCollectionType())); //list(Wrappers.<CollectionNumber>lambdaQuery().eq(CollectionNumber::getCollectionType,collectionNumber.getCollectionType()).like(CollectionNumber::getCollectionNumber,collectionNumberKey));
            if (cNumber != null && StringUtils.isNotEmpty(cNumber.getCollectionNumber())) {
                int currentMaxNumber = Integer.parseInt(cNumber.getCollectionNumber().replaceAll(collectionNumberKey, ""));
                if (!ops.setIfAbsent(String.valueOf(currentMaxNumber + 1))) {
                    ops.increment(1);
                }
            } else {
                if (!ops.setIfAbsent(String.valueOf(benNumber))) {
                    ops.increment(1);
                }
            }
        }

        String number = collectionNumberKey + String.format("%07d", Integer.parseInt(ops.get()));

        collectionNumber.setCollectionNumber(number).setCollectionStatus(COLLECTION_STATUS_ON).setIsDeleted(COLLECTION_NOT_DELETED);
        return save(collectionNumber);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateCollectionNumber(CollectionNumber collectionNumber) {
        Long id = collectionNumber.getId();
        String number = getById(id).getCollectionNumber();
        String name = collectionNumber.getCollectionName();
        int count = collectionNumberDetailService.count(Wrappers.<CollectionNumberDetail>lambdaQuery()
                .eq(CollectionNumberDetail::getCollectionNumber, number));
        if (count > 0){
            collectionNumberDetailService.update(Wrappers.<CollectionNumberDetail>lambdaUpdate()
                    .eq(CollectionNumberDetail::getCollectionNumber, number).set(CollectionNumberDetail::getCollectionName , name));
        }
        return updateById(collectionNumber);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteCollectionNumber(List<String> ids) {
        ids.forEach(id -> {
            String number = getById(id).getCollectionNumber();
            List<CollectionNumberDetail> list = collectionNumberDetailService.list(Wrappers.<CollectionNumberDetail>lambdaQuery().eq(CollectionNumberDetail::getCollectionNumber, number));

            if (CollectionUtils.isNotEmpty(list)) {
                throw new QualityControlBusinessException("此归集号中存在客户数据,不能删除");
            }
        });
        return removeByIds(ids);
    }

    @Override
    public IPage<CollectionNumberVO> getList(String collectionType, String input, String collectionStatus, Page<CollectionNumber> page) {
        Boolean flag1 = isNotNull(collectionType);
        Boolean flag2 = isNotNull(input);
        Boolean flag3 = isNotNull(collectionStatus);

        LambdaQueryWrapper<CollectionNumber> queryWrapper = Wrappers.<CollectionNumber>lambdaQuery()
                .eq(flag1, CollectionNumber::getCollectionType, collectionType)
                .eq(flag3, CollectionNumber::getCollectionStatus, collectionStatus)
                .and(flag2, wrapper -> wrapper
                        .like(CollectionNumber::getCollectionNumber, input)
                        .or()
                        .like(CollectionNumber::getCollectionName, input))
                .orderByAsc(CollectionNumber::getCollectionNumber);

        List<CollectionNumberVO> voList = newArrayList();

        page(page, queryWrapper).getRecords().forEach(l -> {
            CollectionNumberVO vo = getVO(l, CollectionNumberVO.class);
            String collectionNumber = vo.getCollectionNumber();

            Integer count = collectionNumberDetailService
                    .count(Wrappers.<CollectionNumberDetail>lambdaQuery().eq(CollectionNumberDetail::getCollectionNumber, collectionNumber));

            vo.setCollectionCount(count);
            voList.add(vo);
        });

        return getIPage(page, voList, count(queryWrapper));
    }

}
