package cn.cslg.pas.service.impl;

import cn.cslg.pas.common.JsonPage;
import cn.cslg.pas.common.model.PersonnelVO;
import cn.cslg.pas.common.model.dto.*;
import cn.cslg.pas.common.model.vo.*;
import cn.cslg.pas.common.utils.CacheUtils;
import cn.cslg.pas.common.utils.FileUtils;
import cn.cslg.pas.common.utils.SecurityUtils.LoginUtils;
import cn.cslg.pas.common.utils.ThrowException;
import cn.cslg.pas.domain.Product;
import cn.cslg.pas.domain.ProductCategory;
import cn.cslg.pas.domain.asso.AssoProductCategoryPicture;
import cn.cslg.pas.exception.XiaoShiException;
import cn.cslg.pas.mapper.ProductCategoryMapper;
import cn.cslg.pas.mapper.ProductMapper;
import cn.cslg.pas.mapper.asso.AssoProductCategoryPictureMapper;
import cn.cslg.pas.service.IProductCategoryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

/**
 * 产品类别的Service层接口实现类
 *
 * @Author chenyu
 * @Date 2023/3/7
 */
@RequiredArgsConstructor
@Slf4j
@Service
public class ProductCategoryServiceImpl implements IProductCategoryService {
    private final ProductCategoryMapper productCategoryMapper;
    private final AssoProductCategoryPictureMapper assoProductCategoryPictureMapper;
    private final CacheUtils cacheUtils;
    private final LoginUtils loginUtils;
    private final FileUtils fileUtils;
    private final ProductServiceImpl productService;

    /**
     * 新增产品类别
     *
     * @param productCategoryAddNewDTO 产品类别数据对象
     * @param files                    产品类别图片
     */
    @Override
    public void addNew(ProductCategoryAddNewDTO productCategoryAddNewDTO, List<MultipartFile> files) {
        log.info("开始处理【新增产品类别】的业务，参数为：{}, {}", productCategoryAddNewDTO, files);

        //获取当前登陆人信息
        PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
        Integer tenantId = personnelVO.getTenantId();
        Integer createPersonId = personnelVO.getId();
        String createPersonName = personnelVO.getName();

        //1.检查当前租户下该产品类别名称是否被占用
        String productCategoryName = productCategoryAddNewDTO.getProductCategoryName();
        log.info("检查当前租户下该产品类别名称是否被占用");
        int count = productCategoryMapper.countByProductCategoryName(productCategoryName, tenantId);
        if (count > 0) {
            ThrowException.throwXiaoShiException("新增产品类别失败，当前租户下产品类别名称【" + productCategoryName + "】已存在，请尝试更换名称");
        }

        //2.检查许可费率数值是否合法
        Double licenseRate = productCategoryAddNewDTO.getLicenseRate();
        if (licenseRate != null && (licenseRate < 0 || licenseRate > 1)) {
            ThrowException.throwXiaoShiException("新增产品类别失败，许可费率不合法，请填写正确数值");
        }

        //DTO对象赋值给实体类
        ProductCategory productCategory = new ProductCategory();
        BeanUtils.copyProperties(productCategoryAddNewDTO, productCategory);
        productCategory
                .setTenantId(tenantId)
                .setCreatePersonId(createPersonId)
                .setCreatePersonName(createPersonName);

        //数据入产品类别表
        log.info("数据入产品类别表");
        int rows = productCategoryMapper.insert(productCategory);
        if (rows != 1) {
            ThrowException.throwXiaoShiException("新增产品类别失败，数据入产品类别表失败，服务器忙请稍后再次尝试");
        }

        //如果有图片，图片文件上传至本地，获取图片文件的名称、后缀名、url地址，赋值给产品类别图片关联表实体类
        if (files != null && files.size() != 0) {
            ArrayList<AssoProductCategoryPicture> assoProductCategoryPictures = new ArrayList<>();
            for (MultipartFile file : files) {
                //图片文件上传至服务器
                UploadFileDTO fileDTO = fileUtils.uploadFile(file);
                //获取并将产品类别id、图片文件的名称、后缀名、url赋值给产品类别图片关联表实体类
                AssoProductCategoryPicture assoProductCategoryPicture = new AssoProductCategoryPicture()
                        .setProductCategoryId(productCategory.getId())
                        .setName(fileDTO.getName())
                        .setSuffix(fileDTO.getExtName())
                        .setUrl(fileDTO.getPath());
                assoProductCategoryPictures.add(assoProductCategoryPicture);
            }

            log.info("数据入产品类别图片关联表");
            rows = assoProductCategoryPictureMapper.insertBatch(assoProductCategoryPictures);
            if (rows != assoProductCategoryPictures.size()) {
                ThrowException.throwXiaoShiException("新增产品类别失败，数据入产品类别图片关联表失败，服务器忙请稍后再次尝试");
            }
        }

        log.info("新增产品类别完成");

    }

    @Override
    public JsonPage query(ProductCategoryQueryPageDTO productCategoryQueryPageDTO) {
        log.info("开始处理【分页查询产品类别】的业务，参数为：{}", productCategoryQueryPageDTO);

        //获取登陆人信息（取出租户id，控制查询权限）
        PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
        productCategoryQueryPageDTO.setTenantId(personnelVO.getTenantId());

        //分页查询
        Integer current = productCategoryQueryPageDTO.getCurrent();
        Integer size = productCategoryQueryPageDTO.getSize();
        if (current != null && size != null) {
            PageHelper.startPage(current, size);
        }
        List<ProductCategoryVO> ProductCategoryVOs = productCategoryMapper.query(productCategoryQueryPageDTO);
        return JsonPage.restPage(new PageInfo<>(ProductCategoryVOs));
    }

    /**
     * 修改产品类别
     *
     * @param productCategoryUpdateDTO 产品类别数据对象
     * @param files                    产品类别图片
     */
    @Override
    public void update(ProductCategoryUpdateDTO productCategoryUpdateDTO, List<MultipartFile> files) {
        log.info("开始处理【修改产品类别】的业务，参数为：{}, {}", productCategoryUpdateDTO, files);

        //获取登陆人信息（取出租户id，控制权限）
        PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
        Integer tenantId = personnelVO.getTenantId();

        //检查尝试修改的数据是否存在
        Integer productCategoryId = productCategoryUpdateDTO.getId();
        String productCategoryName = productCategoryUpdateDTO.getProductCategoryName();
        log.info("检查尝试修改的数据是否存在");
        int count = productCategoryMapper.countById(productCategoryId);
        if (count == 0) {
            ThrowException.throwXiaoShiException("修改产品类别失败，尝试访问的数据已不存在");
        }

        //检查尝试修改的产品类别名称是否被占用
        log.info("检查尝试修改的产品类别名称是否被占用");
        count = productCategoryMapper.countByIdAndName(productCategoryId, productCategoryName, tenantId);
        if (count > 0) {
            ThrowException.throwXiaoShiException("修改产品类别失败，类别名称【" + productCategoryName + "】已存在，请尝试更换名称");
        }

        //产品类别DTO对象赋值给实体类
        ProductCategory productCategory = new ProductCategory();
        BeanUtils.copyProperties(productCategoryUpdateDTO, productCategory);
        //修改产品类别
        log.info("修改产品类别");
        int rows = productCategoryMapper.updateById(productCategory);
        if (rows != 1) {
            ThrowException.throwXiaoShiException("修改产品类别失败，服务器忙请稍后再次尝试!");
        }

        //先通过产品类别id查询出所有原来的图片文件id
        ArrayList<Integer> oldPictureIds = new ArrayList<>();
        List<ProductCategoryPictureVO> productCategoryPictureVOS = assoProductCategoryPictureMapper.selectByProductCategoryId(productCategoryId);
        for (ProductCategoryPictureVO productCategoryPictureVO : productCategoryPictureVOS) {
            Integer oldPictureId = productCategoryPictureVO.getId();
            oldPictureIds.add(oldPictureId);
        }
        //再从DTO中取出传过来的图片id
        ArrayList<Integer> newOldPictureIds = new ArrayList<>();
        List<ProductCategoryPictureUpateDTO> productCategoryPictureUpateDTOS = productCategoryUpdateDTO.getPictures();
        for (ProductCategoryPictureUpateDTO productCategoryPictureUpateDTO : productCategoryPictureUpateDTOS) {
            Integer newOldPictureId = productCategoryPictureUpateDTO.getId();
            newOldPictureIds.add(newOldPictureId);
        }
        //集合去重
        oldPictureIds.removeAll(newOldPictureIds);

        //判断若去重后的集合（即被前台删除的图片文件）仍有长度，则根据该图片id集合删除产品类别与图片关联表数据
        if (oldPictureIds.size() > 0) {
            log.info("产品类别图片关联表删除被删除的图片");
            assoProductCategoryPictureMapper.deleteByIds(oldPictureIds);
        }

        //判断若有上传新的图片文件，则上传图片并入库
        if (files != null && files.size() != 0) {
            ArrayList<AssoProductCategoryPicture> assoProductCategoryPictures = new ArrayList<>();
            for (MultipartFile file : files) {
                UploadFileDTO fileDTO = fileUtils.uploadFile(file);
                AssoProductCategoryPicture assoProductCategoryPicture = new AssoProductCategoryPicture()
                        .setProductCategoryId(productCategoryId)
                        .setName(fileDTO.getName())
                        .setSuffix(fileDTO.getExtName())
                        .setUrl(fileDTO.getPath());
                assoProductCategoryPictures.add(assoProductCategoryPicture);
            }

            //新数据入产品类别图片关联表
            log.info("新数据入产品类别图片关联表");
            assoProductCategoryPictureMapper.insertBatch(assoProductCategoryPictures);
        }

        log.info("修改产品类别完成");

    }

    @Override
    public void delete(Integer id) {
        log.info("开始处理【删除产品类别】的业务，参数为：{}", id);

        //检查尝试删除的数据是否存在
        log.info("检查尝试删除的数据是否存在");
        int count = productCategoryMapper.countById(id);
        if (count == 0) {
            ThrowException.throwXiaoShiException("删除产品类别失败，访问的数据不存在，请尝试刷新页面");
        }

        //检查该产品类别是否有图片
        count = assoProductCategoryPictureMapper.countByProductCategoryId(id);
        if (count > 0) {
            log.info("产品类别图片关联表删除数据");
            int rows = assoProductCategoryPictureMapper.deleteByProductCategoryId(id);
            if (rows != count) {
                ThrowException.throwXiaoShiException("删除产品类别失败，产品类别图片关联表删除数据失败，服务器忙请稍后再试!");
            }
        }

        //删除产品类别
        log.info("删除产品类别");
        int rows = productCategoryMapper.deleteById(id);
        if (rows != 1) {
            ThrowException.throwXiaoShiException("删除产品类别失败，服务器忙请稍后再试!");
        }

        log.info("删除产品类别完成");

    }

    //返回总的营销数据以及每个的营销数据
    @Override
    public List<ProductCategoryTrendVO> showTrend(ProductCategoryDTO dto) {
        //判断产品类别id是否有内容，没有的话直接返回null
        if (dto.getCategoryId() == null || dto.getCategoryId() == 0) {
            return null;
        }
        //存储每个产品类别信息和营销数据
        List<ProductCategoryTrendVO> trendVOS = new ArrayList<>();
        //存储所有产品类别营销数据
        List<ProductMarketDataTrendVO> saleVOS = new ArrayList<>();
        //存储所有
        ProductCategoryTrendVO totalTrendVO = new ProductCategoryTrendVO();
        //返回总的营销数据 将id设为0
        totalTrendVO.setProductId(0);
        totalTrendVO.setProductName("总产品");
        //查询产品类别id返回的总体营销数据
        List<ProductMarketDataTrendVO> totalSaleVOS = new ArrayList<>();
        if (dto.getTimeUnit() == 2) {//按照年份返回营销数据
            totalSaleVOS = productCategoryMapper.categoryQueryByYear(dto.getCategoryId(), dto.getCategoryArea(), dto.getCompanyName());
        } else if (dto.getTimeUnit() == 1) {//按照季度返回营销数据
            totalSaleVOS = productCategoryMapper.categoryQueryBySeason(dto.getCategoryId(), dto.getCategoryArea(), dto.getCompanyName());
        } else if (dto.getTimeUnit() == null || dto.getTimeUnit() == 0) {//按照月份返回营销数据
            totalSaleVOS = productCategoryMapper.categoryQueryByMonth(dto.getCategoryId(), dto.getCategoryArea(), dto.getCompanyName());
        }
        //把总的营销数据赋值、存入
        totalTrendVO.setSaleVOS(totalSaleVOS);
        trendVOS.add(totalTrendVO);
        //根据传入的类别id、公司名称以及营销地区查询产品id
        List<ProductIdAndNameVO> idNameVOS = new ArrayList<>();
        idNameVOS = productCategoryMapper.queryProductIdAndNameByCategoryId(dto.getCategoryId(), dto.getCompanyName());
        //返回根据产品类别id查询到的每个产品id的营销数据
        //遍历
        for (ProductIdAndNameVO idNameVO : idNameVOS) {//遍历类取得id和名称
            ProductCategoryTrendVO trendVO = new ProductCategoryTrendVO();
            //遍历赋值id和name
            trendVO.setProductId(idNameVO.getProductId());
            trendVO.setProductName(idNameVO.getProductName());
            List<ProductMarketDataTrendVO> temSaleVOS = new ArrayList<>();
            if (dto.getTimeUnit() == 2) {//按照年份返回营销数据
                temSaleVOS = productCategoryMapper.queryByYear(idNameVO.getProductId(), dto.getCategoryArea());
            } else if (dto.getTimeUnit() == 1) {//按照季度返回营销数据
                temSaleVOS = productCategoryMapper.queryBySeason(idNameVO.getProductId(), dto.getCategoryArea());
            } else if (dto.getTimeUnit() == null || dto.getTimeUnit() == 0) {//按照月份返回营销数据
                temSaleVOS = productCategoryMapper.queryByMonth(idNameVO.getProductId(), dto.getCategoryArea());
            }
            trendVO.setSaleVOS(temSaleVOS);
            trendVOS.add(trendVO);
        }
        return trendVOS;
    }


    @Override
    public List<String> getAreaList(GetAreaListDTO dto) {
        PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
        dto.setTenantId(personnelVO.getTenantId());
        List<String> areaList = productCategoryMapper.getAreaList(dto);
        return areaList;

    }


    public List<String> getCompanyList(Integer id) {

        List<String> areaList = new ArrayList<>();
        //根据产品类别id获得产品
        LambdaQueryWrapper<Product> productWrapper = new LambdaQueryWrapper<>();
        productWrapper.eq(Product::getProductCategoryId, id);
        List<Product> products = productService.list(productWrapper);
        products.forEach(item -> {
            if (!areaList.contains(item.getCompanyName())) {
                areaList.add(item.getCompanyName());
            }
        });
        return areaList;
    }
}
