package com.xiaoniu.system.platformsettings.carbrand.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xiaoniu.common.core.constant.Constants;
import com.xiaoniu.common.core.exception.ServiceException;
import com.xiaoniu.common.core.resdata.RowsData;
import com.xiaoniu.common.core.utils.StringUtils;
import com.xiaoniu.common.core.utils.bean.BeanUtils;
import com.xiaoniu.common.security.utils.SecurityUtils;
import com.xiaoniu.system.platformsettings.carbrand.domain.TbCarBrand;
import com.xiaoniu.system.platformsettings.carbrand.dto.AddCarBrandDTO;
import com.xiaoniu.system.platformsettings.carbrand.dto.CarBrandListQueryDTO;
import com.xiaoniu.system.platformsettings.carbrand.dto.EditCarBrandDTO;
import com.xiaoniu.system.platformsettings.carbrand.mapper.TbCarBrandMapper;
import com.xiaoniu.system.platformsettings.carbrand.service.ITbCarBrandService;
import com.xiaoniu.system.platformsettings.carbrand.vo.BatchImportCarInfoVO;
import com.xiaoniu.system.platformsettings.carbrand.vo.BrandListVO;
import com.xiaoniu.system.platformsettings.carbrand.vo.CarBrandDetailsVO;
import com.xiaoniu.system.platformsettings.carbrand.vo.CarBrandListVO;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 车辆品牌信息表 服务实现类
 * </p>
 *
 * @author haoxuyang
 * @since 2024-10-10 05:01:01
 */
@Service
public class TbCarBrandServiceImpl extends ServiceImpl<TbCarBrandMapper, TbCarBrand> implements ITbCarBrandService {

    @Override
    public RowsData<CarBrandListVO> carBrandList(CarBrandListQueryDTO dto) {
        try (Page<Object> page = PageHelper.startPage(dto.getPageNum(), dto.getPageSize())) {
            LambdaQueryWrapper<TbCarBrand> wrapper = new LambdaQueryWrapper<>();
            if (StringUtils.isNotNull(dto.getNo())) {
                wrapper.like(TbCarBrand::getNo, dto.getNo());
            }
            if (StringUtils.isNotNull(dto.getName())) {
                wrapper.like(TbCarBrand::getName, dto.getName());
            }
            if (StringUtils.isNotEmpty(dto.getBeginTime())) {
                wrapper.gt(TbCarBrand::getCreateTime, dto.getBeginTime() + " 00:00:01");
            }
            if (StringUtils.isNotEmpty(dto.getEndTime())) {
                wrapper.lt(TbCarBrand::getCreateTime, dto.getEndTime() + " 23:59:59");
            }
            wrapper.eq(TbCarBrand::getDelFlag, Constants.ZERO);
            wrapper.eq(TbCarBrand::getParentId, Constants.ZERO);
            wrapper.orderByDesc(TbCarBrand::getCreateTime);
            List<CarBrandListVO> list = baseMapper.selectVoList(wrapper, CarBrandListVO.class);
            if (!CollectionUtils.isEmpty(list)) {
                List<Long> ids = list.stream().map(CarBrandListVO::getId).toList();
                List<CarBrandListVO> carBrandList = baseMapper.selectVoList(new LambdaQueryWrapper<TbCarBrand>().in(TbCarBrand::getParentId, ids).eq(TbCarBrand::getDelFlag, Constants.ZERO), CarBrandListVO.class);
                if (!CollectionUtils.isEmpty(carBrandList)) {
                    list.addAll(carBrandList);
                    List<Long> idList = carBrandList.stream().map(CarBrandListVO::getId).toList();
                    List<CarBrandListVO> brandList = baseMapper.selectVoList(new LambdaQueryWrapper<TbCarBrand>().in(TbCarBrand::getParentId, idList).eq(TbCarBrand::getDelFlag, Constants.ZERO), CarBrandListVO.class);
                    if (!CollectionUtils.isEmpty(brandList)) {
                        list.addAll(brandList);
                    }
                }
            }
            if (!CollectionUtils.isEmpty(list)) {
                //处理结构
                return new RowsData<>(buildTree(list), page.getTotal(), dto.getPageNum());
            }
        }
        return new RowsData<>(new ArrayList<>(), 0L, dto.getPageNum());
    }


    @Override
    public void addCarBrand(AddCarBrandDTO dto) {
        TbCarBrand tbCarBrand = new TbCarBrand();
        BeanUtils.copyProperties(dto, tbCarBrand);
        if (StringUtils.isNull(dto.getParentId())) {
            tbCarBrand.setParentId(0L);
            tbCarBrand.setType(Constants.ONE);
        } else {
            TbCarBrand carBrand = baseMapper.selectById(dto.getParentId());
            if (StringUtils.isNull(carBrand)) {
                throw new ServiceException("选择的父级不存在");
            }
            if (Constants.THREE.equals(carBrand.getType())) {
                throw new ServiceException("选择的父级格式不对");
            }
            tbCarBrand.setType(carBrand.getType() + 1);
        }
        try {
            tbCarBrand.setCreateBy(SecurityUtils.getUsername());
        } catch (Exception e) {
            log.error("获取当前登陆人id失败");
        }
        tbCarBrand.setCreateTime(new Date());
        long timestamp = System.currentTimeMillis();
        tbCarBrand.setNo(String.valueOf(timestamp).substring(0, 12));
        baseMapper.insert(tbCarBrand);
    }

    @Override
    public void editCarBrand(EditCarBrandDTO dto) {
        TbCarBrand tbCarBrand = baseMapper.selectById(dto.getId());
        if (StringUtils.isNull(tbCarBrand)) {
            throw new ServiceException("当前车辆信息不存在");
        }
        if ("2".equals(tbCarBrand.getDelFlag())) {
            throw new ServiceException("当前车辆信息已删除");
        }
        BeanUtils.copyProperties(dto, tbCarBrand);
        if (StringUtils.isNull(dto.getParentId()) || 0L == dto.getParentId()) {
            tbCarBrand.setParentId(0L);
            tbCarBrand.setType(Constants.ONE);
        } else {
            TbCarBrand carBrand = baseMapper.selectById(dto.getParentId());
            if (StringUtils.isNull(carBrand)) {
                throw new ServiceException("选择的父级不存在");
            }
            if (Constants.THREE.equals(carBrand.getType())) {
                throw new ServiceException("选择的父级格式不对");
            }
            tbCarBrand.setType(carBrand.getType() + 1);
        }
        try {
            tbCarBrand.setUpdateBy(SecurityUtils.getUsername());
        } catch (Exception e) {
            log.error("获取当前登陆人id失败");
        }
        tbCarBrand.setUpdateTime(new Date());
        baseMapper.updateById(tbCarBrand);
    }

    @Override
    public CarBrandDetailsVO details(Long id) {
        CarBrandDetailsVO detailsVO = baseMapper.selectVoById(id, CarBrandDetailsVO.class);
        if (StringUtils.isNull(detailsVO)) {
            throw new ServiceException("当前车辆信息不存在");
        }
        if ("2".equals(detailsVO.getDelFlag())) {
            throw new ServiceException("当前车辆信息已删除");
        }
        return detailsVO;
    }

    @Override
    public void delCarBrand(Long id) {
        TbCarBrand carBrand = baseMapper.selectById(id);
        if (StringUtils.isNull(carBrand)) {
            throw new ServiceException("当前车辆信息不存在");
        }
        carBrand.setDelFlag("2");
        baseMapper.updateById(carBrand);
    }

    @Override
    public void batchImportCarInfo(MultipartFile file) {
        List<BatchImportCarInfoVO> list = new ArrayList<>();
        try {
            //创建工作簿对象
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook(file.getInputStream());
            //获取工作簿下sheet的个数
            int sheetNum = xssfWorkbook.getNumberOfSheets();
            System.out.println("该excel文件中总共有：" + sheetNum + "个sheet");
            //遍历工作簿中的所有数据

            for (int i = 0; i < sheetNum; i++) {
                //读取第i个工作表
                System.out.println("读取第" + (i + 1) + "个sheet");
                XSSFSheet sheet = xssfWorkbook.getSheetAt(i);
                //获取最后一行的num，即总行数。此处从0开始
                int maxRow = sheet.getLastRowNum();
                for (int row = 1; row <= maxRow; row++) {
                    BatchImportCarInfoVO batchImportCarInfoVO = new BatchImportCarInfoVO();
                    XSSFRow sheetRow = sheet.getRow(row);
                    batchImportCarInfoVO.setBrand(sheetRow.getCell(0) + "");
                    batchImportCarInfoVO.setManufacturer(sheetRow.getCell(1) + "");
                    batchImportCarInfoVO.setVehicleSeries(sheetRow.getCell(2) + "");
                    batchImportCarInfoVO.setYear((sheetRow.getCell(3) + "").replace(".0", ""));
                    batchImportCarInfoVO.setVehicleModel(sheetRow.getCell(4) + "");
                    list.add(batchImportCarInfoVO);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("共有：" + list.size());
        List<BatchImportCarInfoVO> list1 = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BatchImportCarInfoVO::getBrand))), ArrayList::new));
        List<TbCarBrand> brandList = new ArrayList<>();
        for (BatchImportCarInfoVO carInfoVO : list1) {
            TbCarBrand carBrand = new TbCarBrand();
            carBrand.setParentId(0L);
            long nextLong = new Random().nextLong();
            carBrand.setNo(String.valueOf(Math.abs(nextLong)).substring(0, 12));
            carBrand.setYear(Integer.parseInt(carInfoVO.getYear()));
            carBrand.setName(carInfoVO.getBrand());
            carBrand.setManufacturer(carInfoVO.getManufacturer());
            carBrand.setType(1);
            carBrand.setDelFlag("0");
            carBrand.setCreateBy("admin");
            carBrand.setCreateTime(new Date());
            brandList.add(carBrand);
        }
        if (!CollectionUtils.isEmpty(brandList)) {
            baseMapper.insertBatch(brandList);
        }
        Map<String, Long> brandMap = brandList.stream().collect(Collectors.toMap(TbCarBrand::getName, TbCarBrand::getId));
        //处理型号
        List<TbCarBrand> seriesList = new ArrayList<>();
        List<BatchImportCarInfoVO> list2 = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BatchImportCarInfoVO::getVehicleSeries))), ArrayList::new));
        for (BatchImportCarInfoVO carInfoVO : list2) {
            TbCarBrand carBrand = new TbCarBrand();
            carBrand.setParentId(brandMap.get(carInfoVO.getBrand()));
            long nextLong = new Random().nextLong();
            carBrand.setNo(String.valueOf(Math.abs(nextLong)).substring(0, 12));
            carBrand.setYear(Integer.valueOf(carInfoVO.getYear()));
            carBrand.setName(carInfoVO.getVehicleSeries());
            carBrand.setManufacturer(carInfoVO.getManufacturer());
            carBrand.setType(2);
            carBrand.setDelFlag("0");
            carBrand.setCreateBy("admin");
            carBrand.setCreateTime(new Date());
            seriesList.add(carBrand);
            if (seriesList.size() > 500) {
                baseMapper.insertBatch(seriesList);
                seriesList.clear();
            }
        }
        if (!CollectionUtils.isEmpty(seriesList)) {
            baseMapper.insertBatch(seriesList);
        }
//        List<TbCarBrand> seriesList = baseMapper.selectList(new LambdaQueryWrapper<TbCarBrand>().eq(TbCarBrand::getType, Constants.TWO));
        Map<String, Long> seriesMap = seriesList.stream().collect(Collectors.toMap(TbCarBrand::getName, TbCarBrand::getId));
        //处理配置
        List<TbCarBrand> modelList = new ArrayList<>();
        for (BatchImportCarInfoVO carInfoVO : list) {
            TbCarBrand carBrand = new TbCarBrand();
            carBrand.setParentId(seriesMap.get(carInfoVO.getVehicleSeries()));
            long nextLong = new Random().nextLong();
            carBrand.setNo(String.valueOf(Math.abs(nextLong)).substring(0, 12));
            carBrand.setYear(Integer.valueOf(carInfoVO.getYear()));
            carBrand.setName(carInfoVO.getVehicleModel());
            carBrand.setManufacturer(carInfoVO.getManufacturer());
            carBrand.setType(3);
            carBrand.setDelFlag("0");
            carBrand.setCreateBy("admin");
            carBrand.setCreateTime(new Date());
            modelList.add(carBrand);
            if (modelList.size() > 500) {
                baseMapper.insertBatch(modelList);
                modelList.clear();
            }
        }
        if (!CollectionUtils.isEmpty(modelList)) {
            baseMapper.insertBatch(modelList);
        }
    }

    @Override
    public List<CarBrandListVO> getCarListByParentId(CarBrandListQueryDTO dto) {
        LambdaQueryWrapper<TbCarBrand> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotNull(dto.getNo())) {
            wrapper.like(TbCarBrand::getNo, dto.getNo());
        }
        if (StringUtils.isNotNull(dto.getName())) {
            wrapper.like(TbCarBrand::getName, dto.getName());
        }
        if (StringUtils.isNotEmpty(dto.getBeginTime())) {
            wrapper.gt(TbCarBrand::getCreateTime, dto.getBeginTime() + " 00:00:01");
        }
        if (StringUtils.isNotEmpty(dto.getEndTime())) {
            wrapper.lt(TbCarBrand::getCreateTime, dto.getEndTime() + " 23:59:59");
        }
        if (StringUtils.isNotNull(dto.getParentId())) {
            wrapper.eq(TbCarBrand::getParentId, dto.getParentId());
        } else {
            wrapper.eq(TbCarBrand::getParentId, 0);
        }
        wrapper.eq(TbCarBrand::getDelFlag, Constants.ZERO);
        wrapper.orderByDesc(TbCarBrand::getCreateTime);
        return baseMapper.selectVoList(wrapper, CarBrandListVO.class);
    }

    @Override
    public List<BrandListVO> brandList() {
        List<TbCarBrand> carBrands = baseMapper.selectList(new LambdaQueryWrapper<TbCarBrand>().eq(TbCarBrand::getDelFlag, Constants.ZERO).eq(TbCarBrand::getType, Constants.ONE).or().eq(TbCarBrand::getType, Constants.TWO));
        if (CollectionUtils.isEmpty(carBrands)) {
            return new ArrayList<>();
        }
        List<BrandListVO> list = new ArrayList<>();
        List<TbCarBrand> tbCarBrands = carBrands.stream().filter(o -> o.getParentId().equals(0L)).toList();
        if (CollectionUtils.isEmpty(tbCarBrands)) {
            return list;
        }
        for (TbCarBrand tbCarBrand : tbCarBrands) {
            BrandListVO brandListVO = new BrandListVO();
            brandListVO.setLabel(tbCarBrand.getName());
            brandListVO.setValue(String.valueOf(tbCarBrand.getId()));
            List<TbCarBrand> childrenList = carBrands.stream().filter(o -> o.getParentId().equals(tbCarBrand.getId())).toList();
            if (!CollectionUtils.isEmpty(childrenList)) {
                brandListVO.setChildren(childrenList.stream().map(item -> {
                    BrandListVO vo = new BrandListVO();
                    vo.setLabel(item.getName());
                    vo.setValue(String.valueOf(item.getId()));
                    return vo;
                }).toList());
            }
            list.add(brandListVO);
        }
        return list;
    }

    @Override
    public List<CarBrandListVO> brandInfoList() {
        LambdaQueryWrapper<TbCarBrand> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TbCarBrand::getDelFlag, Constants.ZERO);
        wrapper.orderByDesc(TbCarBrand::getCreateTime);
        List<CarBrandListVO> list = baseMapper.selectVoList(wrapper, CarBrandListVO.class);
        if (!CollectionUtils.isEmpty(list)) {
           list = buildTree(list);
        }
        return list;
    }


    public static List<CarBrandListVO> buildTree(List<CarBrandListVO> nodes) {
        List<CarBrandListVO> roots = new ArrayList<>();
        // 将所有节点放入 Map
        Map<Long, List<CarBrandListVO>> nodeMap = nodes.stream().collect(Collectors.groupingBy(CarBrandListVO::getId));

        //首先获取当前列表的顶级集合
        for (CarBrandListVO node : nodes) {
            if (StringUtils.isNotNull(node.getParentId())) {
                List<CarBrandListVO> list = nodes.stream().filter(o -> o.getId().equals(node.getParentId())).toList();
                if (CollectionUtils.isEmpty(list)) {
                    roots.add(node);
                }
            }
        }
        //获取顶级列表的子元素
        for (CarBrandListVO root : roots) {
            recursionFn(nodes, root);
        }
        return roots;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     */
    private static void recursionFn(List<CarBrandListVO> list, CarBrandListVO t) {
        // 得到子节点列表
        List<CarBrandListVO> childList = getChildList(list, t);
        t.setChildren(childList);
        for (CarBrandListVO tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private static List<CarBrandListVO> getChildList(List<CarBrandListVO> list, CarBrandListVO t) {
        List<CarBrandListVO> tlist = new ArrayList<CarBrandListVO>();
        Iterator<CarBrandListVO> it = list.iterator();
        while (it.hasNext()) {
            CarBrandListVO n = (CarBrandListVO) it.next();
            if (n.getParentId().equals(t.getId())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private static boolean hasChild(List<CarBrandListVO> list, CarBrandListVO t) {
        return !CollectionUtils.isEmpty(getChildList(list, t));
    }

}
