package com.github.wxiaoqi.security.admin.biz;

import com.github.wxiaoqi.security.admin.dto.BaseUserMemberExportDTO;
import com.github.wxiaoqi.security.admin.dto.BaseUserMemberExportDataFindDTO;
import com.github.wxiaoqi.security.admin.dto.UserMemberDTO;
import com.github.wxiaoqi.security.admin.dto.UserMemberSaveDTO;
import com.github.wxiaoqi.security.admin.entity.BaseUserMember;
import com.github.wxiaoqi.security.admin.entity.BaseUserMemberExport;
import com.github.wxiaoqi.security.admin.entity.BaseUserMemberLevel;
import com.github.wxiaoqi.security.admin.entity.UserMemberLevel;
import com.github.wxiaoqi.security.admin.mapper.BaseUserMemberExportMapper;
import com.github.wxiaoqi.security.admin.vo.BaseUserMemberExportVo;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.vo.PageDataVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.time.Instant;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author libin
 * @version 1.0
 * @description
 * @data 2019/7/8 16:19
 */
@Service
@Transactional
@Slf4j
public class BaseUserMemberExportBiz extends BaseBiz<BaseUserMemberExportMapper, BaseUserMemberExport> {

    @Autowired
    private UserMemberLevelBiz userMemberLevelBiz;

    @Autowired
    private BaseUserMemberBiz baseUserMemberBiz;

    @Autowired
    private AppUserLoginBiz appUserLoginBiz;


    public void saveUserMember(UserMemberSaveDTO userMemberSaveDTO, Integer userId, String name) {
        if (userMemberSaveDTO != null) {
            UserMemberDTO userMemberDTO = new UserMemberDTO();
            BaseUserMemberLevel level = userMemberLevelBiz.getLevel(userMemberSaveDTO.getMemberLevel());
            Map<String, Integer> phoneAndUserIdMap = appUserLoginBiz.findPhoneAndUserIdMapByPhones(Arrays.asList(userMemberSaveDTO.getPhone()));

            if (phoneAndUserIdMap != null) {
                userMemberDTO.setUserId(phoneAndUserIdMap.get(userMemberSaveDTO.getPhone()));
                userMemberDTO.setMemberLevel(userMemberSaveDTO.getMemberLevel());
                userMemberDTO.setDiscount(level == null ? 0 : (level.getDiscount() == null ? 0 : level.getDiscount()));
                userMemberDTO.setTotalNumber(userMemberSaveDTO.getTotalNumber());
                userMemberDTO.setRentFreeDays(userMemberSaveDTO.getRentFreeDays());
                userMemberDTO.setIsBind(1);
                try {
                    baseUserMemberBiz.updUserMemberByUserId(userMemberDTO);
                } catch (Exception e) {
                    log.error("会员更新或新增错误：【{}】", e.getMessage());
                    throw new BaseException(e);
                }
            }
            BaseUserMemberExport memberExport = BaseUserMemberExport
                    .builder()
                    .username(userMemberSaveDTO.getPhone())
                    .memberLevel(userMemberSaveDTO.getMemberLevel())
                    .totalNumber(userMemberSaveDTO.getTotalNumber())
                    .rentFreeDays(userMemberSaveDTO.getRentFreeDays())
                    .discount(level == null ? 0 : level.getDiscount() == null ? 0 : level.getDiscount())
                    .status(phoneAndUserIdMap == null ? 0 : (phoneAndUserIdMap.get(userMemberSaveDTO.getPhone()) == null ? 0 : 1))
                    .crtId(userId)
                    .crtName(name)
                    .crtTime(Instant.now().toEpochMilli())
                    .isDel(0)
                    .build();
            if (log.isDebugEnabled()) {
                log.debug("当前组装的数据：【{}】", memberExport);
            }
            mapper.insertSelective(memberExport);
        }
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public int importUserMember(List<String[]> userMemberData, Integer userId, String userName) {
        List<BaseUserMemberExport> baseUserMemberExports = new ArrayList<>();

        List<BaseUserMemberLevel> levesls = userMemberLevelBiz.getLevesls();
        Map<Integer, BaseUserMemberLevel> levelAndbaseUserMemberMap = levesls.stream().collect(Collectors.toMap(BaseUserMemberLevel::getLevel, Function.identity()));
        Map<String,Integer> leavelNameAndLeaveMap = levelAndbaseUserMemberMap.values().stream().collect(Collectors.toMap(BaseUserMemberLevel::getName, BaseUserMemberLevel::getLevel));
        List<String> phones = userMemberData.stream().map(x -> x[0]).distinct().collect(Collectors.toList());
        Map<String, Integer> phoneAndUserIdMap = appUserLoginBiz.findPhoneAndUserIdMapByPhones(phones);
        Set<Map.Entry<String, Integer>> leaveNameAndLeaveEntry = leavelNameAndLeaveMap.entrySet();
        Integer memberLevel =1;
        Integer discount = 0;
        for (String[] data : userMemberData) {

            String phone = data[0];
            String memberLevelName = data[1];
            String totalNumber = data[2];
            String rentFreeDays = data[3];

            for (Map.Entry<String, Integer> entry : leaveNameAndLeaveEntry) {
                if (entry.getKey().contains(memberLevelName.substring(0,1))){
                    memberLevel = entry.getValue();
                    discount = levelAndbaseUserMemberMap.get(memberLevel).getDiscount();
                    break;
                }
            }

            if (phoneAndUserIdMap != null && phoneAndUserIdMap.get(phone) != null) {
                UserMemberDTO userMemberDTO = new UserMemberDTO();
                userMemberDTO.setUserId(phoneAndUserIdMap.get(phone));
                userMemberDTO.setMemberLevel(memberLevel);
                userMemberDTO.setDiscount(discount);
                userMemberDTO.setTotalNumber(Integer.valueOf(totalNumber));
                userMemberDTO.setRentFreeDays(Integer.valueOf(rentFreeDays));
                userMemberDTO.setIsBind(1);
                try {
                    baseUserMemberBiz.updUserMemberByUserId(userMemberDTO);
                } catch (Exception e) {
                    log.error("会员更新错误：【{}】", e.getMessage());
                    throw new BaseException(e);
                }
            }

            BaseUserMemberExport memberExport = BaseUserMemberExport
                    .builder()
                    .username(phone)
                    .memberLevel(memberLevel)
                    .totalNumber(Integer.valueOf(totalNumber))
                    .rentFreeDays(Integer.valueOf(rentFreeDays))
                    .discount(discount)
                    .status(phoneAndUserIdMap == null ? 0 : (phoneAndUserIdMap.get(phone) == null ? 0 : 1))
                    .crtId(userId)
                    .crtName(userName)
                    .crtTime(Instant.now().toEpochMilli())
                    .isDel(0)
                    .build();
            if (log.isDebugEnabled()) {
                log.debug("当前组装的数据：【{}】", memberExport);
            }
            baseUserMemberExports.add(memberExport);
        }

        InsertBatch(baseUserMemberExports);
        return baseUserMemberExports.size();
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void InsertBatch(List<BaseUserMemberExport> baseUserMemberExports) {
        mapper.insertList(baseUserMemberExports);
    }

    public List<BaseUserMemberExportDTO> findUserMemberExportDataByPhoneAndHashEffective(String phone) {
        List<BaseUserMemberExportDTO> baseUserMemberExportDTOS = new ArrayList<>();

        Example example = new Example(BaseUserMemberExport.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username", phone);
        criteria.andEqualTo("status", 0);
        criteria.andEqualTo("isDel", 0);
        List<BaseUserMemberExport> baseUserMemberExports = mapper.selectByExample(example);

        if (CollectionUtils.isNotEmpty(baseUserMemberExports)) {
            BaseUserMemberExportDTO baseUserMemberExportDTO;
            for (BaseUserMemberExport userMemberExport : baseUserMemberExports) {
                baseUserMemberExportDTO = new BaseUserMemberExportDTO();
                BeanUtils.copyProperties(userMemberExport, baseUserMemberExportDTO);
                baseUserMemberExportDTOS.add(baseUserMemberExportDTO);
            }
        }
        return baseUserMemberExportDTOS;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateUserMemberExportDataToLoseEfficacyByPhone(String phone) {
        mapper.updateUserMemberExportDataToLoseEfficacyByPhone(phone);
    }

    public PageDataVO<BaseUserMemberExportVo> findUserMemberExportDataPage(BaseUserMemberExportDataFindDTO exportDataFindDTO) {

        PageDataVO<BaseUserMemberExportVo> baseUserMemberExportVoPageDataVO = new PageDataVO<>();
        PageDataVO<BaseUserMemberExportDTO> baseUserMemberExportDataDTOS = PageDataVO.pageInfo(exportDataFindDTO.getPage(), exportDataFindDTO.getLimit(), () -> mapper.findExportDataPage(exportDataFindDTO));
        List<BaseUserMemberExportDTO> userMemberExportDTOS = baseUserMemberExportDataDTOS.getData();
        if (CollectionUtils.isEmpty(userMemberExportDTOS)) {
            return baseUserMemberExportVoPageDataVO;
        }
        List<BaseUserMemberExportVo> baseUserMemberExportVos = new ArrayList<>();
        BaseUserMemberExportVo baseUserMemberExportVo;
        for (BaseUserMemberExportDTO userMemberExportDTO : userMemberExportDTOS) {
            baseUserMemberExportVo = new BaseUserMemberExportVo();
            BeanUtils.copyProperties(userMemberExportDTO, baseUserMemberExportVo);
            baseUserMemberExportVos.add(baseUserMemberExportVo);
        }
        baseUserMemberExportVos.sort(Comparator.comparing(BaseUserMemberExportVo::getCrtTime).reversed());
        baseUserMemberExportVoPageDataVO.setData(baseUserMemberExportVos);
        baseUserMemberExportVoPageDataVO.setPageNum(baseUserMemberExportDataDTOS.getPageNum());
        baseUserMemberExportVoPageDataVO.setPageSize(baseUserMemberExportDataDTOS.getPageSize());
        baseUserMemberExportVoPageDataVO.setTotalCount(baseUserMemberExportDataDTOS.getTotalCount());
        baseUserMemberExportVoPageDataVO.setTotalPage(baseUserMemberExportDataDTOS.getTotalPage());
        return baseUserMemberExportVoPageDataVO;
    }

    public void updateUserMemberExportDataStatus(Integer id) {
        mapper.updateUserMemberExportDataStatusById(id, 1);
    }
}
