package com.xxfc.platform.vehicle.biz;


import com.ace.cache.annotation.Cache;
import com.ace.cache.annotation.CacheClear;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.vo.PageDataVO;
import com.xxfc.platform.vehicle.common.RestResponse;
import com.xxfc.platform.vehicle.constant.RedisKey;
import com.xxfc.platform.vehicle.constant.ResCode.ResCode;
import com.xxfc.platform.vehicle.entity.Vehicle;
import com.xxfc.platform.vehicle.entity.VehicleCata;
import com.xxfc.platform.vehicle.entity.VehiclePlatCata;
import com.xxfc.platform.vehicle.mapper.VehiclePlatCataMapper;
import com.xxfc.platform.vehicle.pojo.Cascade;
import com.xxfc.platform.vehicle.pojo.CataVo;
import com.xxfc.platform.vehicle.pojo.vo.VehiclePlatCataVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Arrays;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Service
@Slf4j
public class VehiclePlatCataBiz extends BaseBiz<VehiclePlatCataMapper, VehiclePlatCata> {

    @Autowired
    VehicleCataBiz vehicleCataBiz;

    //更新
    @Transactional
    @CacheClear(pre = RedisKey.BRANCH_CATA_CACHE)
    public RestResponse update(CataVo cataVo) {
        VehiclePlatCata vehiclePlatCata = new VehiclePlatCata();
        BeanUtils.copyProperties(cataVo, vehiclePlatCata);
        if (vehiclePlatCata.getId() == null || vehiclePlatCata.getId() == 0) {
            vehiclePlatCata.setUpdTime(System.currentTimeMillis());
            insertSelective(vehiclePlatCata);
        } else {
            updateSelectiveById(vehiclePlatCata);
        }
        return RestResponse.suc();
    }

    /**
     * 获取无限级的类别资源
     */
    @Transactional
    @Cache(key = RedisKey.BRANCH_COMPANY_CATA_ALL)
    public JSONObject findTypeTree() throws Exception {
        //默认查询出所有的一级类别
        JSONObject obj = new JSONObject();
        List<VehiclePlatCata> typeList = getAll(0);
        List<Object> list = new ArrayList<>();
        for (VehiclePlatCata cata : typeList) {
            JSONObject treeObject = new JSONObject();
            treeObject.put("id", cata.getId());
            treeObject.put("parentId", cata.getParentId());
            treeObject.put("name", cata.getName());
            treeObject.put("level", cata.getLevel());
            treeObject.put("icon", cata.getIcon());
            treeObject.put("children", getChildren(cata.getId()));
            list.add(treeObject);
        }
        obj.put("cata", list);
        return obj;
    }


    public List<Object> getChildren(Integer parentId) {
        List<Object> list = new ArrayList<>();
        List<VehiclePlatCata> children = getAll(parentId);
        if (children.size() > 0) {
            for (VehiclePlatCata cata : children) {
                JSONObject obj = new JSONObject();
                obj.put("id", cata.getId());
                obj.put("parentId", cata.getParentId());
                obj.put("name", cata.getName());
                obj.put("level", cata.getLevel());
                obj.put("icon", cata.getIcon());
                obj.put("children", getChildren(cata.getId()));
                list.add(obj);
            }
        }
        return list;
    }

    public List<VehiclePlatCata> getAll(Integer parentId) {
        Example example = new Example(VehiclePlatCata.class);
        example.createCriteria().andEqualTo("parentId", parentId).andEqualTo("state", 0);
        example.setOrderByClause("`rank` desc");
        return mapper.selectByExample(example);
    }


    /**
     * 根据车型获取
     *
     * @param modelId
     * @return
     */
    public List<VehiclePlatCata> getByModelId(Integer modelId) {
        List<VehicleCata> vehicleCatas = vehicleCataBiz.selectByExample(new Example.Builder(VehicleCata.class)
                .where(WeekendSqls.<VehicleCata>custom().andEqualTo(VehicleCata::getVehicleModelId, modelId)).build());

        if (vehicleCatas.isEmpty()) {
            return new ArrayList<VehiclePlatCata>();
        } else {
            List<VehiclePlatCata> VehiclePlatCatas = this.selectByExample(new Example.Builder(VehiclePlatCata.class)
                    .where(WeekendSqls.<VehiclePlatCata>custom().andIn(VehiclePlatCata::getId
                            , vehicleCatas.parallelStream().map(VehicleCata::getCataId).distinct()
                                    .collect(Collectors.toList()))).build());
            return VehiclePlatCatas;
        }
    }


    /**
     * 级联添加
     *
     * @param cascade
     * @return
     */

    public ObjectRestResponse addCascade(Cascade<VehiclePlatCata> cascade) {

        //取出一级标签
        VehiclePlatCata parent = cascade.getParent();
        //取出二级标签
        List<VehiclePlatCata> childrens = cascade.getChildren();

        if (parent==null||childrens == null) {
            throw new BaseException("The tag name cannot be empty!");
        }
        parent.setCrtTime(System.currentTimeMillis());
        //插入一级标签获得id
        parent.setIsMore(0);
        parent.setRank(0);
        mapper.insertSelective(parent);
        Integer parentId = parent.getId();

        List<VehiclePlatCata> vehiclePlatCatas = childrens.parallelStream().filter(vehiclePlatCata -> {
            vehiclePlatCata.setParentId(parentId);
            vehiclePlatCata.setCrtTime(System.currentTimeMillis());
            if(null == vehiclePlatCata.getRank()) {
                vehiclePlatCata.setRank(1);
            }
            return vehiclePlatCata.getState() == 0;
        }).filter(vpc -> StringUtils.isNotBlank(vpc.getName())).collect(Collectors.toList());

        if (vehiclePlatCatas.size() == 0) {
            throw new BaseException("No valid subtag!");
        }
        mapper.addPlatCataList(vehiclePlatCatas);

        return ObjectRestResponse.succ();
    }


    /**
     * 根据父类id获取子标签
     *
     * @param parentId
     * @return
     */
    public ObjectRestResponse<List<VehiclePlatCata>> fingCatasByParentId(Integer parentId) {

        Example example = Example.builder(VehiclePlatCata.class)
                .where(WeekendSqls.<VehiclePlatCata>custom()
                        .andEqualTo(VehiclePlatCata::getParentId, parentId)
                        .andEqualTo(VehiclePlatCata::getState, 0))
                .orderByAsc("rank")
                .build();
        List<VehiclePlatCata> vpcs = mapper.selectByExample(example);
        return ObjectRestResponse.succ(vpcs);
    }


    /**
     * 分页或不分页,获取一级标签及其子标签
     *
     * @param sort
     * @param page
     * @param limit
     * @return
     */
    public ObjectRestResponse getCascades(Integer page, Integer limit, Integer sort, Integer goodsType, String name) {
        try {
            //标签列表页面
            if (sort == null || sort == 0) {
                return getPage(page, limit, goodsType, name);
            }

            //增加车型页面
            if (sort == 1) {
                return getList(goodsType);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);;
        }
        return ObjectRestResponse.createFailedResult(ResCode.FIND_VEHICLE_PLAT_FAILE.getCode(), ResCode.FIND_VEHICLE_PLAT_FAILE.getDesc());
    }


    @Cache(key = RedisKey.BRANCH_COMPANY_CATA_LIST+ "{1}")
    private ObjectRestResponse getList(Integer goodsType) {
        //获取一级标签
        Example example = Example.builder(VehiclePlatCata.class)
                .where(WeekendSqls.<VehiclePlatCata>custom()
                        .andEqualTo(VehiclePlatCata::getParentId, 0)
                        .andEqualTo(VehiclePlatCata::getState, 0)
                        .andEqualTo(VehiclePlatCata::getGoodsType, goodsType)
                )
                .orderByAsc("isMore", "rank")
                .build();
        //分页查询父类
        List<VehiclePlatCata> parentvpcs = mapper.selectByExample(example);
        //传入一级标签集集合,或去一二级标签集合
        ArrayList<Cascade<VehiclePlatCata>> cascades = getCascades(parentvpcs);

        return ObjectRestResponse.succ(cascades);
    }

    @Cache(key = RedisKey.BRANCH_COMPANY_CATA_PAGE)
    private ObjectRestResponse getPage(Integer page, Integer limit, Integer goodsType, String name) {
        //获取一级标签
        WeekendSqls<VehiclePlatCata> weekendSqls = WeekendSqls.<VehiclePlatCata>custom();
        if(null != goodsType){
            weekendSqls.andEqualTo(VehiclePlatCata::getGoodsType, goodsType);
        }
        weekendSqls.andEqualTo(VehiclePlatCata::getParentId, 0)
                .andEqualTo(VehiclePlatCata::getState, 0);
        if (StringUtils.isNotBlank(name)) {
            weekendSqls.andLike(VehiclePlatCata::getName, "%" + name + "%");
        }
        Example example = Example.builder(VehiclePlatCata.class)
                .where(weekendSqls)
                .orderByAsc("rank")
                .build();

        //分页查询一级标签并分类
        PageDataVO opdvo = PageDataVO.pageInfo(page, limit, () -> mapper.selectByExample(example));
        List<VehiclePlatCata> parentvpcs = opdvo.getData();

        //传入一级标签集集合,或去一二级标签集合
        ArrayList<Cascade<VehiclePlatCata>> cascades = getCascades(parentvpcs);

        //用一二级标签集合,替换原来的一级标签集合
        opdvo.setData(cascades);
        return ObjectRestResponse.succ(opdvo);
    }

    private ArrayList<Cascade<VehiclePlatCata>> getCascades(List<VehiclePlatCata> parentvpcs) {
        ArrayList<Cascade<VehiclePlatCata>> cascades = new ArrayList();
        //获取二级标签
        for (VehiclePlatCata parentvpc : parentvpcs) {
            Example exa = Example.builder(VehiclePlatCata.class)
                    .where(WeekendSqls.<VehiclePlatCata>custom()
                            .andEqualTo(VehiclePlatCata::getParentId, parentvpc.getId())
                            .andEqualTo(VehiclePlatCata::getState, 0))
                    .orderByAsc("rank")
                    .build();
            List<VehiclePlatCata> childrenvpcs = mapper.selectByExample(exa);
            //一级标签和其二级标签存入Cascade中集合中
            cascades.add(new Cascade<VehiclePlatCata>(parentvpc, childrenvpcs));

        }
        return cascades;
    }


    /**
     * 查询一个一级标签及其子标签
     *
     * @param id
     * @return
     */
    public ObjectRestResponse findCascade(Integer id) {
        VehiclePlatCata vehiclePlatCata = new VehiclePlatCata();
        vehiclePlatCata.setId(id);
        vehiclePlatCata.setState(0);
        VehiclePlatCata result = mapper.selectOne(vehiclePlatCata);

        Example example = Example.builder(VehiclePlatCata.class)
                .where(WeekendSqls.<VehiclePlatCata>custom()
                        .andEqualTo(VehiclePlatCata::getParentId, id)
                        .andEqualTo(VehiclePlatCata::getState, 0))
                .orderByAsc("rank")
                .build();
        List<VehiclePlatCata> vpcs = mapper.selectByExample(example);
        return ObjectRestResponse.succ(new Cascade<VehiclePlatCata>(result, vpcs));
    }


    /**
     * 更新和添加
     *
     * @param cas
     * @return
     */
    @Transactional
    public ObjectRestResponse updateAndAdd(Cascade<VehiclePlatCata> cas) {

        if (cas == null || cas.getParent() == null) {
            return ObjectRestResponse.paramIsEmpty();
        }

        //通过判断一级标签是否有id来判断是更新还是添加
        if (cas.getParent().getId() == null || cas.getParent().getId() == 0) {
            return addCascade(cas);
        } else {

            return updateCascade(cas);
        }

    }


    /**
     * 修改
     *
     * @param cas
     * @return
     */

    public ObjectRestResponse updateCascade(Cascade<VehiclePlatCata> cas) {

        try {
            VehiclePlatCata parentVPC = cas.getParent();
            List<VehiclePlatCata> children = cas.getChildren();
            if (children == null || parentVPC == null) {
                throw new BaseException("标签名不能为空！");
            }
            //设置更新时间
            parentVPC.setUpdTime(System.currentTimeMillis());
            //更新一级标签
            updateSelectiveById(parentVPC);
            //获取子标签签


            //过滤无用数据
            List<VehiclePlatCata> VehiclePlatCatas = children.parallelStream()
                    .filter(vpc -> vpc.getId() != null || vpc.getState() == 0)
                    .filter(vpc -> StringUtils.isNotBlank(vpc.getName()))
                    .collect(Collectors.toList());
            //判断有效数据是否为空
            if (VehiclePlatCatas.size() == 0) {
                throw new BaseException("父标签无效");
            }
            //遍历
            for (VehiclePlatCata VehiclePlatCata : VehiclePlatCatas) {

                //判断子标签是更新还是新增
                if (VehiclePlatCata.getId() == null || VehiclePlatCata.getId() == 0) {
                    VehiclePlatCata.setUpdTime(System.currentTimeMillis());
                    VehiclePlatCata.setParentId(parentVPC.getId());
                    //添加
                    insertSelective(VehiclePlatCata);
                } else {
                    //判断是否是删除

                    if (VehiclePlatCata.getState() == 1) {
                        Integer id = VehiclePlatCata.getId();
                        VehicleCata vehicleCata = new VehicleCata();
                        vehicleCata.setCataId(id);
                        //修改车型和标签的中间表
                        vehicleCata.setIsdel(1);
                        vehicleCataBiz.updateIsdalByVehicleCataId(vehicleCata);
                    }

                    //更新
                    VehiclePlatCata.setUpdTime(System.currentTimeMillis());
                    updateSelectiveById(VehiclePlatCata);
                }

            }
            return ObjectRestResponse.succ();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return ObjectRestResponse.createFailedResult(ResCode.UPDATE_VEHICLE_RANK_FAIL.getCode(), ResCode.UPDATE_VEHICLE_RANK_FAIL.getDesc());
    }

    /**
     * 修改rank
     *
     * @param id
     * @param rank
     * @return
     */
    public ObjectRestResponse updateParentRank(Integer id, Integer rank) {

        try {
            VehiclePlatCata vehiclePlatCata = new VehiclePlatCata();
            vehiclePlatCata.setId(id);
            vehiclePlatCata.setRank(rank);
            updateSelectiveById(vehiclePlatCata);
            return ObjectRestResponse.succ();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ObjectRestResponse.createFailedResult(ResCode.UPDATE_VEHICLE_RANK_FAIL.getCode(), ResCode.UPDATE_VEHICLE_RANK_FAIL.getDesc());
        }
    }

    /**
     * 查询当前车型拥有的标签
     *
     * @param ids
     * @return
     */
    public ObjectRestResponse<List<VehiclePlatCata>> getCatasByIds(String ids) {
        Example exa = Example.builder(VehiclePlatCata.class).where(
                WeekendSqls.<VehiclePlatCata>custom()
                        .andIn(VehiclePlatCata::getId, Arrays.asList(ids.split(",")))
                        .andEqualTo(VehiclePlatCata::getState, 0)
        ).build();
        List<VehiclePlatCata> vehiclePlatCatas = selectByExample(exa);
        return ObjectRestResponse.succ(vehiclePlatCatas);
    }

    /**
     * 删除一级标签及其子标签
     *
     * @param id
     * @return
     */
    @Transactional
    public ObjectRestResponse deleteCascadeById(Integer id) {
        //修改一级标签
        VehiclePlatCata vehiclePlatCata = new VehiclePlatCata();
        vehiclePlatCata.setId(id);
        vehiclePlatCata.setState(1);
        updateSelectiveById(vehiclePlatCata);

        //修改子标签
        VehiclePlatCata vpc = new VehiclePlatCata();
        vpc.setState(1);
        mapper.updateByExampleSelective(vpc, Example.builder(VehiclePlatCata.class)
                .andWhere(WeekendSqls.<VehiclePlatCata>custom()
                        .andEqualTo(VehiclePlatCata::getParentId, id)).build());
        return ObjectRestResponse.succ();
    }


    /**
     * 修改客户端查询条件
     *
     * @param id
     * @param startUsing
     * @return
     */
    @Transactional
    public ObjectRestResponse setStartUsingById(Integer id, Integer startUsing) {
        VehiclePlatCata vehiclePlatCata = new VehiclePlatCata();
        vehiclePlatCata.setId(id);
        vehiclePlatCata.setStartUsing(startUsing);
        updateSelectiveById(vehiclePlatCata);
        return ObjectRestResponse.succ();
    }


    /**
     * 修改单选还是多选
     *
     * @param id
     * @param isMore
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ObjectRestResponse setIsore(Integer id, Integer isMore) {
        VehiclePlatCata vehiclePlatCata = new VehiclePlatCata();
        vehiclePlatCata.setId(id);
        vehiclePlatCata.setIsMore(isMore);
        updateSelectiveById(vehiclePlatCata);
        return ObjectRestResponse.succ();
    }

    public Map<Integer, List<VehiclePlatCata>> groupCatasByParent(String catasStr) {
        List<Integer> catasIds = Pattern.compile(",").splitAsStream(catasStr).map((s) -> Integer.parseInt(s)).collect(Collectors.toList());
        List<VehiclePlatCata> catas = selectByExample(new Example.Builder(VehiclePlatCata.class)
                .where(WeekendSqls.<VehiclePlatCata>custom().andIn(VehiclePlatCata::getId, catasIds)).build());
        Map<Integer, List<VehiclePlatCata>> vpcMap = new HashMap<Integer, List<VehiclePlatCata>>();
        for (VehiclePlatCata vpc : catas) {
            List<VehiclePlatCata> vpcs = vpcMap.get(vpc.getParentId());
            if (null == vpcs) {
                vpcs = new ArrayList<VehiclePlatCata>();
            }
            vpcs.add(vpc);
            vpcMap.put(vpc.getParentId(), vpcs);
        }
        return vpcMap;
    }

    public List<VehiclePlatCataVo> findVehicleCategoryByParentId(Integer parentId){
         List<VehiclePlatCataVo> cataVos = new ArrayList<>();
        Example example = new Example(VehiclePlatCata.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("parentId",parentId);
        criteria.andEqualTo("state",0);
        List<VehiclePlatCata> vehiclePlatCatas = mapper.selectByExample(example);
        if (CollectionUtils.isEmpty(vehiclePlatCatas)){
            return cataVos;
        }
        cataVos= JSON.parseObject(JSON.toJSONString(vehiclePlatCatas), new TypeReference<List<VehiclePlatCataVo>>() {
        });
        return cataVos;
    }

    private VehiclePlatCataBiz getMyBiz() {
        return AopContext.currentProxy() != null ? (VehiclePlatCataBiz) AopContext.currentProxy() : this;
    }
}
