package com.hzs.member.base.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.enums.EBonusStage;
import com.hzs.common.core.enums.EBonusStageStatus;
import com.hzs.common.core.enums.EBonusStageType;
import com.hzs.common.core.enums.EMemberChildNodeType;
import com.hzs.common.domain.member.achieve.CuMemberRetailDetail;
import com.hzs.common.domain.member.base.CuMember;
import com.hzs.member.base.mapper.CuMemberRetailDetailMapper;
import com.hzs.member.base.param.CuMemberPointPairParam;
import com.hzs.member.base.service.ICuMemberService;
import com.hzs.member.base.service.ICumemberRetailDetailService;
import com.hzs.member.structure.controller.dto.CuMemberDetailDTO;
import com.hzs.member.structure.controller.dto.CuMemberPointDTO;
import com.hzs.member.structure.controller.vo.ChildCodeVO;
import com.hzs.member.structure.controller.vo.CuMemberPointDetailVO;
import com.hzs.member.structure.controller.vo.CuMemberPointListVO;
import com.hzs.member.structure.controller.vo.CuMemberThreeFrameworkVO;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class ICumemberRetailDetailServiceImpl extends ServiceImpl<CuMemberRetailDetailMapper, CuMemberRetailDetail> implements ICumemberRetailDetailService {
    @Autowired
    private ICuMemberService iCuMemberService;
    @Autowired
    private ICumemberRetailDetailService  iCumemberRetailDetailService;
    @Override
    public List<ChildCodeVO> getChildList(String memberCode, Integer stage, Integer stageStatus, String settleTableName) {
        return baseMapper.getChildList(memberCode,stage,stageStatus,settleTableName);
    }


    @Override
    public Integer getFindCumemberRetailDetail(String settleTableName) {
        return baseMapper.getFindCumemberRetailDetail(settleTableName);
    }

    @Override
    public List<Tree<String>> convertToNodeList(CuMemberRetailDetail cuMemberRetailDetail,String settleTableName) {
        Map<Long, CuMember> memberMap = createMemberMap(cuMemberRetailDetail);
        Map<String, CuMemberPointDTO> collect = createPointMap(cuMemberRetailDetail,settleTableName);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 构建node
        List<Map<String, Object>> nodeList = new ArrayList<>();
        for (EMemberChildNodeType type : EMemberChildNodeType.values()) {
            if (type == EMemberChildNodeType.ROOT) {
                nodeList.add(makeNode(
                        type.getId(),
                        type.getParentId(),
                        type.getLabel(),
                        sdf.format(cuMemberRetailDetail.getCreationTime()),
                        cuMemberRetailDetail.getStageSort(),
                        cuMemberRetailDetail.getChildNode(),
                        cuMemberRetailDetail.getPkMember(),
                        cuMemberRetailDetail.getStage(),
                        memberMap
                ));
                continue;
            }

            Integer point = (Integer) type.getPointValue(cuMemberRetailDetail);
            Long pointMember = (Long) type.getPointMemberValue(cuMemberRetailDetail);

            nodeList.add(makeNode(
                    type.getId(),
                    type.getParentId(),
                    type.getLabel(),
                    safeFormatTime(collect, pointMember,point, sdf),
                    safeStageSort(collect,pointMember,point),
                    point,
                    pointMember,
                    safeStage(collect,pointMember,point),
                    memberMap
            ));
        }
        // 构造树结构
        return TreeUtil.build(nodeList, EMemberChildNodeType.ROOT.getParentId(), (node, tree) -> {
            tree.setId((String) node.get("id"));
            tree.setParentId((String) node.get("parentId"));
            tree.setName((String) node.get("label"));
            tree.putExtra("memberCode", node.get("memberCode"));
            tree.putExtra("memberName", node.get("memberName"));
            tree.putExtra("nodeCode", node.get("nodeCode"));
            tree.putExtra("pointMember", node.get("pointMember"));
            tree.putExtra("creationTime", node.get("creationTime"));
            tree.putExtra("position", node.get("position"));
            tree.putExtra("stage", node.get("stage"));
            tree.putExtra("stageSort", node.get("stageSort"));
        });
    }

    private Integer safeStage(Map<String, CuMemberPointDTO> collect,Long pkMember, Integer point) {
        CuMemberPointDTO cuMemberPointDTO = collect.get(pkMember + "-" + point);
        if (cuMemberPointDTO == null || cuMemberPointDTO.getStage() == null) {
            return null;
        }
        return cuMemberPointDTO.getStage();
    }

    private Integer safeStageSort(Map<String, CuMemberPointDTO> collect,Long pkMember, Integer point) {
        CuMemberPointDTO cuMemberPointDTO = collect.get(pkMember + "-" + point);
        if (cuMemberPointDTO == null || cuMemberPointDTO.getStageSort() == null) {
            return null;
        }
        return cuMemberPointDTO.getStageSort();
    }

    private String safeFormatTime(Map<String, CuMemberPointDTO> collect,Long pkMember, Integer pointKey, SimpleDateFormat sdf) {
        var detail = collect.get(pkMember + "-" + pointKey);
        if (detail == null || detail.getCreationTime() == null) {
            return null;
        }
        return sdf.format(detail.getCreationTime());
    }

    @Override
    public CuMemberRetailDetail getCuMemberRetailDetailByUserId(Long userId, Integer stage, Integer stageStatus, String childNode, String settleTableName) {
        return baseMapper.getCuMemberRetailDetailByUserId(userId,stage,stageStatus,childNode,settleTableName);
    }

    @Override
    public List<ChildCodeVO> getChildListByUserId(Long userId, Integer stage, Integer stageStatus, String settleTableName) {
        return baseMapper.getChildListByUserId(userId,stage,stageStatus,settleTableName);
    }

    @Override
    public List<CuMemberThreeFrameworkVO> getCuMemberRetailDetailList(String settleTableName, String memberCode, Integer stage, Integer stageStatus) {
        List<CuMemberThreeFrameworkVO> cuMemberRetailDetailDTOList = baseMapper.getCuMemberRetailDetailDTOList(settleTableName, memberCode, stage, stageStatus);
        cuMemberRetailDetailDTOList.forEach(item -> {
            item.setPointTypeLabel(EBonusStageType.getEBonusStageTypeByValue(item.getPointType()).getLabel());
            item.setStageLabel(EBonusStage.getEBonusStageByValue(item.getStage()).getLabel());
            item.setStageStatusLabel(EBonusStageStatus.getEBonusStageStatusLabel(item.getStageStatus()).getLabel());
        });
        return cuMemberRetailDetailDTOList;
    }

    @Override
    public CuMemberPointDetailVO getPointDetailByUserId(Long userId, Long pointMember, Integer stage, Integer point, String settleTableName) {
        CuMemberPointDTO cuMemberPointDTO = baseMapper.getPointDetailByUserId(pointMember, stage, point, settleTableName);
        CuMemberDetailDTO cuMemberDetailDTO = iCuMemberService.getCuMemberDetailById(pointMember);
        if (cuMemberDetailDTO == null || cuMemberPointDTO == null) {
            return null;
        }
        return makeCuMemberPointDetailVO(cuMemberDetailDTO,cuMemberPointDTO,point);
    }

    @Override
    public List<CuMemberPointDTO> getPointDetailListByPoints(List<CuMemberPointPairParam> pairList, Integer stage, String settleTableName) {
        return baseMapper.getPointDetailListByPoints(pairList,stage,settleTableName);
    }

    @Override
    public List<CuMemberPointListVO> convertToList(CuMemberRetailDetail cuMemberRetailDetail, String settleTableName) {
        ArrayList<CuMemberPointListVO> list = new ArrayList<>();
        Map<Long, CuMember> memberMap = createMemberMap(cuMemberRetailDetail);
        Map<String, CuMemberPointDTO> collect = createPointMap(cuMemberRetailDetail,settleTableName);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (EMemberChildNodeType type : EMemberChildNodeType.values()) {
            if (type == EMemberChildNodeType.ROOT) {
                continue;
            }
            Integer point = (Integer) type.getPointValue(cuMemberRetailDetail);
            Long pointMember = (Long) type.getPointMemberValue(cuMemberRetailDetail);
            CuMemberPointListVO build = CuMemberPointListVO.builder()
                    .point(type.getId())
                    .pkMember(pointMember)
                    .childNode(point)
                    .build();
            if (pointMember != null && memberMap.containsKey(pointMember)) {
                build.setMemberCode(memberMap.get(pointMember).getMemberCode());
                build.setMemberName(memberMap.get(pointMember).getMemberName());
            }
            build.setStage(safeStage(collect,pointMember,point));
            build.setStageSort(safeStageSort(collect,pointMember,point));
            build.setCreationTime(safeFormatTime(collect,pointMember,point,sdf));
            list.add(build);
        }
        return list;
    }

    private Map<String, CuMemberPointDTO> createPointMap(CuMemberRetailDetail cuMemberRetailDetail,String settleTableName){
        // 所有会员id
        List<Long> ids = new ArrayList<>();
        // 过滤空的会员id
        Stream.of(
                cuMemberRetailDetail.getPointMember11(), cuMemberRetailDetail.getPointMember12(),
                cuMemberRetailDetail.getPointMember21(), cuMemberRetailDetail.getPointMember22(), cuMemberRetailDetail.getPointMember23(), cuMemberRetailDetail.getPointMember24(),
                cuMemberRetailDetail.getPointMember31(), cuMemberRetailDetail.getPointMember32(), cuMemberRetailDetail.getPointMember33(), cuMemberRetailDetail.getPointMember34(),
                cuMemberRetailDetail.getPointMember35(), cuMemberRetailDetail.getPointMember36(), cuMemberRetailDetail.getPointMember37(), cuMemberRetailDetail.getPointMember38()
        ).filter(Objects::nonNull).forEach(ids::add);
        // 所有点位信息
        List<Integer> points = new ArrayList<>();
        // 过滤所有空的点位信息
        Stream.of(
                cuMemberRetailDetail.getPoint11(), cuMemberRetailDetail.getPoint12(),
                cuMemberRetailDetail.getPoint21(), cuMemberRetailDetail.getPoint22(), cuMemberRetailDetail.getPoint23(), cuMemberRetailDetail.getPoint24(),
                cuMemberRetailDetail.getPoint31(), cuMemberRetailDetail.getPoint32(), cuMemberRetailDetail.getPoint33(), cuMemberRetailDetail.getPoint34(),
                cuMemberRetailDetail.getPoint35(), cuMemberRetailDetail.getPoint36(), cuMemberRetailDetail.getPoint37(), cuMemberRetailDetail.getPoint38()
        ).filter(Objects::nonNull).forEach(points::add);
        // 查询所有点位信息创建时间
        List<CuMemberPointDTO> cuMemberPointDTOList;
        if (points.isEmpty() || ids.isEmpty()) {
            cuMemberPointDTOList = Collections.emptyList();
        }else {
            List<CuMemberPointPairParam> pairList = new ArrayList<>();
            Iterator<Long> idIter = ids.iterator();
            Iterator<Integer> pointIter = points.iterator();
            while (idIter.hasNext() && pointIter.hasNext()) {
                pairList.add(new CuMemberPointPairParam(idIter.next(), pointIter.next()));
            }
            cuMemberPointDTOList = iCumemberRetailDetailService.getPointDetailListByPoints(pairList,cuMemberRetailDetail.getStage(),settleTableName);
        }
        return cuMemberPointDTOList.stream()
                .collect(Collectors.toMap(
                        dto -> dto.getPkMember() + "-" + dto.getChildNode(),
                        Function.identity(),
                        (a, b) -> a
                ));
    }

    private Map<Long, CuMember> createMemberMap(CuMemberRetailDetail cuMemberRetailDetail){
        // 所有会员id
        List<Long> ids = new ArrayList<>();
        ids.add(cuMemberRetailDetail.getPkMember());
        // 过滤空的会员id
        Stream.of(
                cuMemberRetailDetail.getPointMember11(), cuMemberRetailDetail.getPointMember12(),
                cuMemberRetailDetail.getPointMember21(), cuMemberRetailDetail.getPointMember22(), cuMemberRetailDetail.getPointMember23(), cuMemberRetailDetail.getPointMember24(),
                cuMemberRetailDetail.getPointMember31(), cuMemberRetailDetail.getPointMember32(), cuMemberRetailDetail.getPointMember33(), cuMemberRetailDetail.getPointMember34(),
                cuMemberRetailDetail.getPointMember35(), cuMemberRetailDetail.getPointMember36(), cuMemberRetailDetail.getPointMember37(), cuMemberRetailDetail.getPointMember38()
        ).filter(Objects::nonNull).forEach(ids::add);
        // 查找对应会员信息
        List<CuMember> members;
        if (ids.isEmpty()) {
            members = Collections.emptyList();
        } else {
            members = iCuMemberService.listByIds(new ArrayList<>(ids));
        }

        return members.stream()
                .collect(Collectors.toMap(CuMember::getPkId, Function.identity(), (a, b) -> a));
    }

    private CuMemberPointDetailVO makeCuMemberPointDetailVO(CuMemberDetailDTO cuMemberDetailDTO, CuMemberPointDTO cuMemberPointDTO,Integer point) {
        return CuMemberPointDetailVO.builder()
                .memberCode(cuMemberDetailDTO.getMemberCode())
                .memberName(cuMemberDetailDTO.getMemberName() + "-" + point)
                .awardsName(cuMemberDetailDTO.getAwardsName())
                .vertexName(cuMemberDetailDTO.getVertexName())
                .creationTime(cuMemberPointDTO.getCreationTime())
                .build();
    }


    private Map<String, Object> makeNode(String id, String parentId, String label,String creationTime,Integer stageSort,Integer pointMember,
                                         Long memberId, Integer stage,Map<Long, CuMember> memberMap) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", id);
        map.put("parentId", parentId);
        map.put("label", label);
        map.put("nodeCode", label);

        if (memberId != null && memberMap.containsKey(memberId)) {
            CuMember member = memberMap.get(memberId);
            map.put("memberCode", member.getMemberCode());
            map.put("memberName", member.getMemberName());
            map.put("pointMember", pointMember);
            map.put("position",member.getMemberCode() + "-"  + stage + "-" + stageSort + "(" + pointMember + ")");
            map.put("creationTime", creationTime);
            map.put("stageSort", stageSort);
            map.put("stage", stage);
        } else {
            // 没有信息置空
            map.put("memberCode", "");
            map.put("memberName", "");
            map.put("pointMember", "");
            map.put("position", "");
            map.put("creationTime", "");
            map.put("stageSort", "");
            map.put("stage", "");
        }
        return map;
    }

}
