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

import cn.newfeifan.mall.framework.common.pojo.PageParam;
import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.newfeifan.mall.module.distri.controller.app.sharepath.vo.*;
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.orderpercentage.OrderPercentageDO;
import cn.newfeifan.mall.module.distri.dal.dataobject.partitioncrash.PartitionCrashDO;
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.dal.mysql.partitioncrash.PartitionCrashMapper;
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.socialstatus.SocialStatusService;
import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
import cn.newfeifan.mall.module.member.service.user.MemberUserService;
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.validation.annotation.Validated;


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 java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
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 SocialStatusService socialStatusService;

    @Resource
    private OrderPercentageMapper orderPercentageMapper;

    @Resource
    private IntegralService integralService;

    @Resource
    private PartitionCrashMapper partitionCrashMapper;


    @Override
    public Long createSharePath(SharePathSaveReqVO createReqVO) {
        // 插入
        SharePathDO sharePath = BeanUtils.toBean(createReqVO, SharePathDO.class);
        sharePathMapper.insert(sharePath);
        // 返回
        return sharePath.getId();
    }


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

        // 判断当前直推人是否有父亲
        Boolean has = hasParent(createReqVO.getDescendant());
        if (has) {
            throw exception(HAS_PARENT);
        }
        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.getName(),
                    ancestor.getNickname(),
                    ancestor.getMobile(),

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

        OrderPercentageDO orderPercentageDO = orderPercentageMapper.selectList().get(0);
        duserService.updateDuserSocial(createReqVO.getAncestor(), Long.valueOf(orderPercentageDO.getRegisterAncestorSocialStatus()), SocialStatusEnum.REGISTER_ANCESTOR_SOCIAL.getStatus());

    }

    @Override
    public void createSharePathByUserId(Long userId) {
        Boolean has = hasParent(userId);
        if (has) {
            return;
        }
        // 如果是没有父亲, 将其推荐人设置为平台
        SharePathSaveReqVO build = SharePathSaveReqVO.builder()
                .ancestor(PT_ID)
                .descendant(userId)
                .build();
        createSharePathByUserId(build);
    }

    @Override
    public Boolean hasParent(Long descendant) {
        SharePathDO sharePathDO = sharePathMapper.selectOne(new LambdaQueryWrapperX<SharePathDO>()
                .eqIfPresent(SharePathDO::getDescendant, descendant)
                .eqIfPresent(SharePathDO::getDepth, 1));
        return sharePathDO != null;
    }

    @Override
    public AppSharePathRespVO getTeam(PageParam pageParam) {
        Long userId = getLoginUserId();

        //获取团队数
        LambdaQueryWrapperX<SharePathDO> wrapper = new LambdaQueryWrapperX<>();
        wrapper.eq(SharePathDO::getAncestor, userId);
        // +1 加自己
        Long teamCount = sharePathMapper.selectCount(wrapper) + 1;

        //获取推荐人
        SharePathDO sharePathDO = sharePathMapper.selectOne(new LambdaQueryWrapperX<SharePathDO>()
                .eq(SharePathDO::getDescendant, userId)
                .eq(SharePathDO::getDepth, 1));
        SharePathRespVO ancestor = BeanUtils.toBean(sharePathDO, SharePathRespVO.class);
        if (ancestor != null) {
            ancestor.setAvatar(getAvatar(ancestor.getAncestor()));
            getSocialStatus(ancestor, ancestor.getAncestor());
            //获取最大可用额度
//            setHighQuota(ancestor, ancestor.getAncestor());

            //获取团队数
            Long descendantsCount = sharePathMapper.selectCount(new LambdaQueryWrapper<SharePathDO>()
                    .eq(SharePathDO::getAncestor, ancestor.getAncestor())
            );
            ancestor.setDescendantsCount(descendantsCount);
            //里面放的是本人的兄弟分区额度
            ancestor.setResidueSocial(getBrotherSocial(userId));
            //获取用户名
            ancestor.setUsername(memberUserService.getUser(ancestor.getAncestor()).getUsername());
        }

        //获取团队成员
        PageResult<SharePathDO> descendants = sharePathMapper.selectPage(pageParam, new LambdaQueryWrapperX<SharePathDO>()
                .eq(SharePathDO::getAncestor, userId)
                .eq(SharePathDO::getDepth, 1)
                .orderByAsc(SharePathDO::getDepth)
        );
        PageResult<SharePathRespVO> result = BeanUtils.toBean(descendants, SharePathRespVO.class);
        result.getList().forEach(item -> {
            item.setAvatar(getAvatar(item.getDescendant()));
            getSocialStatus(item, item.getDescendant());

            Long descendantsCount = sharePathMapper.selectCount(new LambdaQueryWrapper<SharePathDO>()
                    .eq(SharePathDO::getAncestor, item.getDescendant())
            );
            item.setDescendantsCount(descendantsCount);

            //获取最大可用额度
//            setHighQuota(item, item.getDescendant());

            //获取剩余碰撞额度 + 待确权直推奖
            item.setResidueSocial(getSonSocial(item.getDescendant()));
            //获取用户名
            item.setUsername(memberUserService.getUser(item.getDescendant()).getUsername());
        });


        return AppSharePathRespVO.builder()
                .teamCount(teamCount)
                .ancestor(ancestor)
                .descendants(result).build();
    }

    /**
     * 获取本用户兄弟分区的剩余额度值
     *
     * @param userId 用户编号
     * @return 剩余额度值
     */
    private Long getBrotherSocial(Long userId) {
        PartitionCrashDO yesterdayCrash = getYesterdayCrash(userId, 1);
        return yesterdayCrash == null ? 0 : yesterdayCrash.getBrotherPrice();
    }

    /**
     * 获取昨日分区信息
     *
     * @param userId 用户编号
     * @return 分区信息
     */
    private PartitionCrashDO getYesterdayCrash(Long userId, int today) {
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT); // 今天的开始时间，即午夜12点
        LocalDateTime localDateTime = todayStart.minusDays(today);
        String yesterdayNo = "CRASH:" + userId + ":" + localDateTime;
        PartitionCrashDO partitionCrashDO = partitionCrashMapper.selectOne(new LambdaQueryWrapperX<PartitionCrashDO>().eqIfPresent(PartitionCrashDO::getPartNo, yesterdayNo));
        List<PartitionCrashDO> partitionCrashDOS = partitionCrashMapper.selectList((new LambdaQueryWrapperX<PartitionCrashDO>()
                .eq(PartitionCrashDO::getUserId, userId))
                .apply("date(create_time) < date(now())")
        );

        //判断这个用户不是第一次碰撞并且没有查询到昨天的碰撞记录,有可能是昨天或者更早定时任务没有启动导致的,所以再往前查几天
        if(!partitionCrashDOS.isEmpty() && partitionCrashDO == null){
            return getYesterdayCrash(userId, ++today);
        }
        return partitionCrashDO;
    }

    /**
     * 获取直推人后代分区的剩余额度值
     *
     * @param userId 用户编号
     * @return 剩余额度值
     */
    private Long getSonSocial(Long userId) {
        PartitionCrashDO yesterdayCrash = getYesterdayCrash(userId, 1);
        return yesterdayCrash == null ? 0 : yesterdayCrash.getSonPrice();
    }

    /**
     * 获取最高可获取积分
     *
     * @param sharePath 对象
     * @param userId    用户编号
     */
    private void setHighQuota(SharePathRespVO sharePath, Long userId) {
        IntegralDO integralDO = integralService.selectByUser(userId);
        if (integralDO != null) {
            sharePath.setHigh_quota(integralDO.getHighQuota());
        }
    }

    private void getSocialStatus(SharePathRespVO sharePathRespVO, Long userId) {
        if (Objects.equals(userId, PT_ID)) return;
        DuserDO duser = duserService.getDuserByUser(userId);
        SocialStatusDO socialStatus = socialStatusService.getSocialStatus(duser.getSocialStatusId());
        sharePathRespVO.setSocialStatusLevel(socialStatus.getLevel());
        sharePathRespVO.setSocialStatusLevelName(socialStatus.getName());
    }

    private String getAvatar(Long userId) {
        return memberUserService.getUser(userId).getAvatar();
    }

    @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() {


        return null;
    }

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

    @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());

    }


}