package cn.newfeifan.mall.module.distri.service.sharepath;

import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.newfeifan.mall.module.distri.dal.dataobject.duser.DuserDO;
import cn.newfeifan.mall.module.distri.dal.dataobject.integral.IntegralDO;
import cn.newfeifan.mall.module.distri.dal.dataobject.ordercalc.OrderCalcDO;
import cn.newfeifan.mall.module.distri.dal.dataobject.orderpercentage.OrderPercentageDO;
import cn.newfeifan.mall.module.distri.dal.dataobject.socialstatus.SocialStatusDO;
import cn.newfeifan.mall.module.distri.dal.mysql.orderpercentage.OrderPercentageMapper;
import cn.newfeifan.mall.module.distri.enums.SocialStatusEnum;
import cn.newfeifan.mall.module.distri.service.duser.DuserService;
import cn.newfeifan.mall.module.distri.service.integral.IntegralService;
import cn.newfeifan.mall.module.distri.service.ordercalc.OrderCalcService;
import cn.newfeifan.mall.module.distri.service.orderpercentage.OrderPercentageService;
import cn.newfeifan.mall.module.distri.service.socialstatus.SocialStatusService;
import cn.newfeifan.mall.module.distri.service.socialstatuschangelog.SocialStatusChangeLogService;
import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserRespVO;
import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
import cn.newfeifan.mall.module.member.convert.user.MemberUserConvert;
import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
import cn.newfeifan.mall.module.member.service.user.MemberUserService;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

import cn.newfeifan.mall.module.distri.controller.admin.sharepath.vo.*;
import cn.newfeifan.mall.module.distri.dal.dataobject.sharepath.SharePathDO;
import cn.newfeifan.mall.framework.common.pojo.PageResult;
import cn.newfeifan.mall.framework.common.util.object.BeanUtils;

import cn.newfeifan.mall.module.distri.dal.mysql.sharepath.SharePathMapper;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.module.distri.constant.DistriConstants.BOOS_ID;
import static cn.newfeifan.mall.module.distri.constant.DistriConstants.PT_ID;
import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.*;

/**
 * 分销用户关系 Service 实现类
 *
 * @author 非繁人
 */
@Service
@Validated
public class SharePathServiceImpl implements SharePathService {

    @Resource
    private SharePathMapper sharePathMapper;

    @Resource
    @Lazy
    private DuserService duserService;
    @Resource
    private MemberUserService memberUserService;
    @Resource
    private OrderCalcService orderCalcService;

    @Resource
    @Lazy
    private IntegralService integralService;

    @Resource
    private SocialStatusChangeLogService socialStatusChangeLogService;

    @Resource
    private OrderPercentageMapper orderPercentageMapper;

    @Resource
    private SocialStatusService socialStatusService;
    @Resource
    private OrderPercentageService orderPercentageService;

    @Override
    public void createSharePathByUserId(SharePathSaveReqVO createReqVO, Boolean isNew) {

        // 如果直推人为空, 则直接结束
        if (createReqVO.getDescendant() == null) {
            return;
        }

        // 判断当前直推人是否有父亲
        Boolean has = hasParent(createReqVO.getDescendant());
        if (has) {
            throw exception(HAS_PARENT);
        }
        if (createReqVO.getAncestor() == null) {
            createReqVO.setAncestor(BOOS_ID);
        }
        MemberUserDO ancestor = memberUserService.getUser(createReqVO.getAncestor());
        MemberUserDO descendant = memberUserService.getUser(createReqVO.getDescendant());

        // 创建直推人以及推荐人的关系
        // 需要判断当前推荐人跟直推人是否已经存在于用户表(duser)了
        duserService.hasUserAndCreat(createReqVO);

        // 存储他们之间的关系
        if (!Objects.equals(createReqVO.getDescendant(), PT_ID)) {
            sharePathMapper.addNode(
                    createReqVO.getAncestor(),
                    ancestor.getUsername(),
                    ancestor.getNickname(),
                    ancestor.getMobile(),

                    createReqVO.getDescendant(),
                    descendant.getUsername(),
                    descendant.getNickname(),
                    descendant.getMobile());
        }

        if (!isNew) {
            return;
        }
        OrderPercentageDO orderPercentageDO = orderPercentageMapper.selectList().get(0);
        duserService.updateDuserSocial(createReqVO.getAncestor(), Long.valueOf(orderPercentageDO.getRegisterAncestorSocialStatus()), SocialStatusEnum.REGISTER_ANCESTOR_SOCIAL.getStatus());
        socialStatusChangeLogService.createSocialStatusChangeLog(createReqVO.getAncestor(), Long.valueOf(orderPercentageDO.getRegisterAncestorSocialStatus()), createReqVO.getAncestor(), SocialStatusEnum.REGISTER_ANCESTOR_SOCIAL);

    }

    @Override
    public void createSharePathByUserId(List<Long> userIds) {

        for (Long userId : userIds) {
            Boolean has = hasParent(userId);
            if (has) {
                continue;
            }
            // 如果是没有父亲, 将其推荐人设置为平台
            SharePathSaveReqVO build = SharePathSaveReqVO.builder()
                    .ancestor(BOOS_ID)
                    .descendant(userId)
                    .build();
            createSharePathByUserId(build, true);
        }
    }

    private Boolean hasParent(Long descendant) {
        List<SharePathDO> sharePathDO = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>()
                .eqIfPresent(SharePathDO::getDescendant, descendant)
                .eqIfPresent(SharePathDO::getDepth, 1));
        return !sharePathDO.isEmpty();
    }

    @Override
    public void updateSharePath(SharePathSaveReqVO updateReqVO) {
        // 校验存在
        validateSharePathExists(updateReqVO.getId());
        // 更新
        SharePathDO updateObj = BeanUtils.toBean(updateReqVO, SharePathDO.class);
        sharePathMapper.updateById(updateObj);
    }

    @Override
    public void deleteSharePath(Long id) {
        // 校验存在
        validateSharePathExists(id);
        // 删除
        sharePathMapper.deleteById(id);
    }

    private void validateSharePathExists(Long id) {
        if (sharePathMapper.selectById(id) == null) {
            throw exception(SHARE_PATH_NOT_EXISTS);
        }
    }

    @Override
    public SharePathDO getSharePath(Long id) {
        return sharePathMapper.selectById(id);
    }

    @Override
    public PageResult<SharePathDO> getSharePathPage(SharePathPageReqVO pageReqVO) {
        return sharePathMapper.selectPage(pageReqVO);
    }


    @Override
    public TreeNode getTree(Long userId, Integer maxDepth) {
        // 如果user为空, 则查询全部信息
        if (userId == null) {
            userId = PT_ID;
        }
        DuserDO sharePathDO = duserService.getDuserByUser(userId);
        // 查询层级范围
        List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>().eq(SharePathDO::getAncestor, userId)
                .between(SharePathDO::getDepth, 1, maxDepth));

        List<TreeNode> deep = sharePathDO2TreeNode(sharePathDOS);
        if (maxDepth > 1) {
            List<Long> descs = sharePathDOS.stream().filter(k -> k.getDepth() > 1).map(SharePathDO::getDescendant).collect(Collectors.toList());
            // 获取大于1层级的数据
            if (!descs.isEmpty()) {
                List<SharePathDO> descList = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>().ne(SharePathDO::getAncestor, 1).in(SharePathDO::getDescendant, descs));
                List<TreeNode> treeNodes1 = sharePathDO2TreeNode(descList);
//                deep = deep.stream().filter(k -> k.getDeep() == 1).collect(Collectors.toList());
                deep.addAll(treeNodes1);
            }
        }
        // 只需要深度等于1的数据
        deep = deep.stream().filter(k -> k.getDeep() == 1).collect(Collectors.toList());

        // 整合结构
        List<TreeNode> treeNodes = listWithTree(deep, userId);

        return TreeNode.builder()
                .phone(sharePathDO.getMobile())
                .name(sharePathDO.getName())
                .nickname(sharePathDO.getNickName())
                .children(treeNodes).build();
    }

    @Override
    public TreeNode getTreeByNameOrMobile(SharePathTreeReqVO sharePathTreeReqVO) {
        //拿到当前用户ID
        Long userId = getUserIdByNameOrMobile(sharePathTreeReqVO.getNickName(), sharePathTreeReqVO.getMobile());

        //拿到推荐人ID
        Long ancestor = sharePathMapper.selectAncestorByDescendant(userId);
        return getTree(ancestor, sharePathTreeReqVO.getMaxDepth());
    }

    @Override
    public MemberUserRespVO getMemberUser(Long userId) {
        MemberUserDO user = memberUserService.getUser(userId);
        MemberUserRespVO memberUserRespVO = MemberUserConvert.INSTANCE.convert03(user);

        SharePathDO sharePathDO = sharePathMapper.selectOne(new LambdaQueryWrapper<SharePathDO>()
                .eq(SharePathDO::getDescendant, userId)
                .eq(SharePathDO::getDepth, 1)
        );
        if (sharePathDO != null) {
            memberUserRespVO.setAncNickName(sharePathDO.getAncNickName());
            memberUserRespVO.setRecommenderdId(sharePathDO.getAncestor());
        }

        DuserDO duser = duserService.getDuserByUser(memberUserRespVO.getId());
        //没有这个用户直接就返回
        if (duser == null) return memberUserRespVO;

        IntegralDO integral = integralService.getIntegralByUserId(userId);
        if (integral != null) {
            memberUserRespVO.setCurrentQuota(integral.getCurrentQuota());
            OrderPercentageDO orderPercentageDO = orderPercentageService.queryStatus();
            memberUserRespVO.setHighQuotaTotal(integral.getHighQuotaTotal() + new BigDecimal(orderPercentageDO.getBaseMaxQuota()).longValue());
            memberUserRespVO.setConsumptionPoints(integral.getConsumptionPoints());
        }

        SocialStatusDO socialStatus = socialStatusService.getSocialStatus(duser.getSocialStatusId());
        if (socialStatus == null) return memberUserRespVO;
        memberUserRespVO.setCurrentMemberWorthLevelName(socialStatus.getName());
        memberUserRespVO.setCurrentMemberWorthLevel(socialStatus.getLevel());

        return memberUserRespVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(MemberUserUpdateReqVO updateReqVO) {
        // 判断当前用户是否更新推荐人
        Long ancestor = sharePathMapper.selectAncestorByDescendant(updateReqVO.getId());
        if (!Objects.equals(updateReqVO.getRecommenderdId(), ancestor)) {
            // 如果用户为游客,将清除游客标识
            updateReqVO.setVisitor(false);

            // 如果有更新的话,要清除原来的关系树
            List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapper<SharePathDO>()
                    .eq(SharePathDO::getAncestor, updateReqVO.getId()));
            List<SharePathDO> sharePathDOS1;
            List<SharePathDO> children = null;
            if (!sharePathDOS.isEmpty()) {
                sharePathDOS1 = sharePathMapper.selectList(new LambdaQueryWrapper<SharePathDO>()
                        .in(SharePathDO::getDescendant, sharePathDOS.stream().map(SharePathDO::getDescendant).collect(Collectors.toList())));
                children = sharePathMapper.selectList(new LambdaQueryWrapper<SharePathDO>()
                        .in(SharePathDO::getDescendant, sharePathDOS.stream().map(SharePathDO::getDescendant).collect(Collectors.toList()))
                        .eq(SharePathDO::getDepth, 1));
                // 逻辑删除旧的关系树
                sharePathMapper.deleteBatchIds(sharePathDOS1.stream().map(SharePathDO::getId).collect(Collectors.toList()));
            }
            sharePathMapper.delete(new LambdaQueryWrapper<SharePathDO>()
                    .eq(SharePathDO::getDescendant, updateReqVO.getId()));

            // 添加新的关系树
            createSharePathByUserId(SharePathSaveReqVO.builder().ancestor(updateReqVO.getRecommenderdId()).descendant(updateReqVO.getId()).build(), false);

            if (children != null && !children.isEmpty()) for (SharePathDO child : children) {
                createSharePathByUserId(SharePathSaveReqVO.builder().ancestor(child.getAncestor()).descendant(child.getDescendant()).build(), false);
            }

        }

        // 更新
        memberUserService.updateUser(updateReqVO);
    }

    private void createSharePath(List<TreeNode> children) {
        for (TreeNode child : children) {
            createSharePathByUserId(SharePathSaveReqVO.builder().ancestor(child.getParentId()).descendant(child.getUserId()).build(), false);
            if (child.getChildren() != null) {
                createSharePath(child.getChildren());
            }
        }
    }

    private Long getUserIdByNameOrMobile(String name, String mobile) {
        if (!StringUtils.isEmpty(name)) {
            List<DuserDO> duserDOS = duserService.getDuserByName(name);
            if (duserDOS.isEmpty()) {
                throw exception(DUSER_NAME_NOT_EXISTS);
            } else if (duserDOS.size() > 1) {
                throw exception(DUSER_NAME_IS_NOT_ONLY_ONE);
            }

            return duserDOS.get(0).getUserId();
        } else {
            DuserDO duserDO = duserService.getDuserByMobile(mobile);
            if (duserDO == null) {
                throw exception(DUSER_MOBILE_NOT_EXISTS);
            }
            return duserDO.getUserId();
        }
    }


    public List<TreeNode> sharePathDO2TreeNode(List<SharePathDO> sharePathDOS) {
        return sharePathDOS.stream().map(k -> TreeNode.builder()
                .phone(k.getDescPhone())
                .name(k.getDescName())
                .deep(k.getDepth())
                .parentId(k.getAncestor())
                .userId(k.getDescendant())
                .sort(k.getSort())
                .nickname(k.getDescNickName()).build()).collect(Collectors.toList());
    }


    public static List<TreeNode> listWithTree(List<TreeNode> all, Long pid) {
        // 2、找到一级父类，再通过级联去查询儿子
        return all.stream().filter(k ->
                k.getParentId().equals(pid)   //查询父类
        ).map(k -> {
            k.setChildren(getChildren(k, all));
            return k;//查询子类菜单
        }).collect(Collectors.toList());
    }

    public static List<TreeNode> getChildren(TreeNode root, List<TreeNode> all) {
        // 递归查找所有后代的儿子
        return all.stream().filter(k -> k.getParentId().equals(root.getUserId()))
                .map(k -> {
                    k.setChildren(getChildren(k, all));
                    return k;
                }).collect(Collectors.toList());
    }

    @Override
    public void transferenceRela(SharePathtransFerenceRelaReqVO sharePathtransFerenceRelaReqVO) {
        // todo 转让用户关系
    }

    @Override
    public SharePathDO getSharePathByDescendant(Long userId) {

        List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>().eqIfPresent(SharePathDO::getDescendant, userId)
                .eqIfPresent(SharePathDO::getDepth, 1));
        if (sharePathDOS.isEmpty()) {
            return null;
        }
        return sharePathDOS.get(0);
    }

    @Override
    public List<OrderCalcDO> selectSons(Long userId, List<Long> userIds) {
        List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>()
                .eq(SharePathDO::getAncestor, userId));
        List<Long> allDescendants = sharePathDOS.stream().map(SharePathDO::getDescendant).collect(Collectors.toList());
//        List<Long> allDescendants = sharePathMapper.findAllDescendants(userId);
        if (allDescendants.isEmpty()) {
            return Collections.emptyList();
        }
        // 查询出两个list的并集
        List<Long> unionList = unionList(userIds, allDescendants);
        if (unionList.isEmpty()) {
            return Collections.emptyList();
        }
        // 获取这个分区的所有订单的合赢奖
        return calcQuota(unionList);

    }

    private List<OrderCalcDO> calcQuota(List<Long> unionList) {

        // 根据当前userId， 查询当日，计算出来的订单
        // 创建日期
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT); // 今天的开始时间，即午夜12点
        LocalDateTime todayEnd = todayStart.plusDays(1);

        return orderCalcService.queryTodayCalcByUserIds(todayStart, todayEnd, unionList);

    }

    @Override
    public List<OrderCalcDO> selectBrothers(Long userId, List<Long> userIds, MemberUserDO user) {
        List<Long> sortedSiblings = new ArrayList<>();
        // 先查询出他的父亲
        List<SharePathDO> sharePathDO = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>().eq(SharePathDO::getDepth, 1).eq(SharePathDO::getDescendant, userId));
        if (sharePathDO.isEmpty()) {
            sortedSiblings = sharePathMapper.findLessSortedSiblings(userId);
        } else {
            // 再根据父亲查询他的所有儿子
//            List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>()
//                    .eq(SharePathDO::getDepth, 1)
//                    .eq(SharePathDO::getAncestor, sharePathDO.get(0).getAncestor()));
            // 后续加了游客身份所以,查询的时候要隔离游客的兄弟分区和用户的兄弟分区
            List<SharePathDO> sharePathDOS = sharePathMapper.selectListByVisitor(sharePathDO.get(0).getAncestor(), user.getVisitor());
            //最后再进行排序
            sortedSiblings = filterByDescendant(sharePathDOS, userId);
            // 查询兄弟的所有儿子
            sortedSiblings.addAll(findSons(sortedSiblings));
        }

        if (sortedSiblings.isEmpty()) {
            return Collections.emptyList();
        }
        // 查询出两个list的并集
        List<Long> unionList = unionList(userIds, sortedSiblings);
        if (unionList.isEmpty()) {
            return Collections.emptyList();
        }
        // 获取这个分区的所有订单的合赢奖
        return calcQuota(unionList);
    }

    private List<Long> findSons(List<Long> sortedSiblings) {
        List<Long> longs = new ArrayList<>();
        for (Long sortedSibling : sortedSiblings) {
            List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>()
                    .eq(SharePathDO::getAncestor, sortedSibling));
            if (sharePathDOS.isEmpty()) {
                continue;
            }
            List<Long> collect = sharePathDOS.stream().map(SharePathDO::getDescendant).collect(Collectors.toList());
            longs.addAll(collect);
        }
        return longs.stream().distinct().collect(Collectors.toList());
    }


    public List<Long> filterByDescendant(List<SharePathDO> sharePaths, Long descendantId) {
        // 首先，找到特定 descendantId 的 sort 值
        SharePathDO reference = sharePaths.stream()
                .filter(sharePath -> sharePath.getDescendant().equals(descendantId))
                .findFirst()
                .orElse(null);

        if (reference == null) {
            throw new IllegalArgumentException("Descendant with ID " + descendantId + " not found");
        }

        // 过滤出所有 sort 值大于找到的 sort 值的记录
        return sharePaths.stream()
                .filter(sharePath ->
                        {
                            if (reference.getSort() != null && sharePath.getSort() != null) {
                                return sharePath.getSort() > reference.getSort();
                            }
                            return false;
                        }
                )
                .map(SharePathDO::getDescendant)
                .collect(Collectors.toList());
    }


    @Override
    public Long queryParentBySonUserId(Long userId) {

        List<SharePathDO> sharePathDO = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>()
                .eqIfPresent(SharePathDO::getDescendant, userId).eqIfPresent(SharePathDO::getDepth, 1));
        if (sharePathDO.isEmpty()) {
            return 1L;
        } else {
            return sharePathDO.get(0).getAncestor();
        }


    }

    @Override
    public List<DuserDO> selectSon(Long userId) {

        // 查询当前用户的所有后代
        List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>().eqIfPresent(SharePathDO::getAncestor, userId));

        List<Long> duserId = sharePathDOS.stream().map(SharePathDO::getDescendant).collect(Collectors.toList());

        if (duserId.isEmpty()) {
            return Collections.emptyList();
        }

        return duserService.selectUserByUserIds(duserId);

    }

    @Override
    public List<Long> sonsId(Long userId) {
        List<SharePathDO> sharePathDOS = sharePathMapper.selectList(new LambdaQueryWrapperX<SharePathDO>().eq(SharePathDO::getAncestor, userId));
        return sharePathDOS.stream().map(SharePathDO::getDescendant).collect(Collectors.toList());

    }


    public List<Long> unionList(List<Long> orderUserId, List<Long> userId) {
        return userId.stream()
                .filter(orderUserId::contains)
                .collect(Collectors.toList());

//        return Stream.concat(orderUserId.stream(), userId.stream()).distinct().collect(Collectors.toList());

    }

    @Override
    public PageResult<SharePathRespVO> getDescendants(SharePathPageReqVO pageReqVO) {
        LambdaQueryWrapperX<SharePathDO> wrapper = new LambdaQueryWrapperX<SharePathDO>()
                .eq(SharePathDO::getAncestor, pageReqVO.getAncestor());
        if (pageReqVO.getDepth() != null) {
            wrapper.eq(SharePathDO::getDepth, 1);
        } else {
            wrapper.ne(SharePathDO::getDepth, 1);
        }

        PageResult<SharePathDO> sharePathDOPageResult = sharePathMapper.selectDescendantsPage(pageReqVO);
        PageResult<SharePathRespVO> result = BeanUtils.toBean(sharePathDOPageResult, SharePathRespVO.class);
        List<SharePathRespVO> list = result.getList();
        list.forEach(sharePath -> sharePath.setAvatar(memberUserService.getUser(sharePath.getDescendant()).getAvatar()));
        return result;
    }


}