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.ProductMarketData;
import cn.cslg.pas.domain.Structure;
import cn.cslg.pas.domain.asso.AssoProductPatent;
import cn.cslg.pas.domain.asso.AssoProductPicture;
import cn.cslg.pas.domain.asso.AssoStructurePatent;
import cn.cslg.pas.domain.asso.AssoStructurePicture;
import cn.cslg.pas.exception.XiaoShiException;
import cn.cslg.pas.mapper.ProjectMapper;
import cn.cslg.pas.mapper.asso.AssoProductPictureMapper;
import cn.cslg.pas.mapper.ProductMapper;
import cn.cslg.pas.mapper.asso.AssoProductPatentMapper;
import cn.cslg.pas.mapper.asso.AssoStructurePatentMapper;
import cn.cslg.pas.service.IAssoStructurePictureService;
import cn.cslg.pas.service.IProductMarketDataService;
import cn.cslg.pas.service.IProductService;
import cn.cslg.pas.service.IStructureService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 产品的Service层接口实现类
 *
 * @Author chenyu
 * @Date 2023/3/8
 */
@RequiredArgsConstructor
@Slf4j
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {
    private final ProductMapper productMapper;
    private final AssoProductPictureMapper assoProductPictureMapper;
    private final AssoProductPatentMapper assoProductPatentMapper;
    private final AssoStructurePatentMapper assoStructurePatentMapper;
    private final ProjectMapper projectMapper;
    private final IStructureService structureService;
    private final IAssoStructurePictureService assoStructurePictureService;
    private final IProductMarketDataService productMarketDataService;
    private final CacheUtils cacheUtils;
    private final LoginUtils loginUtils;
    private final FileUtils fileUtils;
    /**
     * 新增产品
     *
     * @param productAddNewDTO 新增产品的DTO对象
     * @param files            产品图片
     */
    @Override
    public void addNew(ProductAddNewDTO productAddNewDTO, List<MultipartFile> files) {
        log.info("开始处理【新增产品】的业务，参数为：{}, {}", productAddNewDTO, files);

        //检查产品名称是否被占用
        String productName = productAddNewDTO.getProductName();
        Integer productCategoryId = productAddNewDTO.getProductCategoryId();
        log.info("检查产品名称是否被占用");
        int count = productMapper.countByProductName(productName, productCategoryId);
        if (count > 0) {
            String message = "新增产品失败，产品名称【" + productName + "】已存在，请尝试更换名称";
            log.info("{}", message);
            throw new XiaoShiException(message);
        }

        Double licenseRate = productAddNewDTO.getLicenseRate();
        if (licenseRate != null && (licenseRate < 0 || licenseRate > 1)) {
            String message = "新增产品失败，许可费率不合法，请填写正确数值";
            log.info("{}", message);
            throw new XiaoShiException(message);
        }

        //产品新增DTO对象赋值给实体类
        Product product = new Product();
        BeanUtils.copyProperties(productAddNewDTO, product);
        //获取当前登陆人信息并赋值给实体类
        PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
        product
                .setCreatePersonId(personnelVO.getId())
                .setCreatePersonName(personnelVO.getName())
                .setCreatePersonTenantId(personnelVO.getTenantId());
        //数据入产品表
        log.info("数据入产品表");
        int rows = productMapper.insert(product);
        if (rows != 1) {
            String message = "新增产品失败，服务器忙请稍后再试!";
            log.info("{}", message);
            throw new XiaoShiException(message);
        }

        //数据入产品专利关联表(若有专利)
        String patentNo = productAddNewDTO.getPatentNo();
        if (patentNo != null) {
            AssoProductPatent assoProductPatent = new AssoProductPatent()
                    .setPatentNo(patentNo)
                    .setProductId(product.getId());
            log.info("数据入产品专利关联表");
            assoProductPatentMapper.insert(assoProductPatent);
        }


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

            log.info("数据入产品图片关联表");
            rows = assoProductPictureMapper.insertBatch(assoProductPictures);
            if (rows != assoProductPictures.size()) {
                String message = "新增产品失败，数据入产品图片关联表失败，服务器忙请稍后再试!";
                log.info("{}", message);
                throw new XiaoShiException(message);
            }
        }

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

    }

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

        //检查尝试修改的数据是否存在
        Integer productId = productUpdateDTO.getId();
        log.info("检查尝试修改的数据是否存在");
        int count = productMapper.countById(productId);
        if (count == 0) {
            String message = "修改产品失败，尝试访问的数据已不存在";
            log.info("{}", message);
            throw new XiaoShiException(message);
        }

        //产品DTO对象赋值给实体类
        Product product = new Product();
        BeanUtils.copyProperties(productUpdateDTO, product);
        //修改产品
        log.info("修改产品");
        int rows = productMapper.updateById(product);
        if (rows != 1) {
            String message = "修改产品失败，服务器忙请稍后再次尝试!";
            log.info("{}", message);
            throw new XiaoShiException(message);
        }

        //先根据产品id查询出原来的产品图片文件id
        List<ProductPictureVO> productPictureVOs = assoProductPictureMapper.selectByProductId(productId);
        ArrayList<Integer> oldPictureIds = new ArrayList<>();
        for (ProductPictureVO productPictureVO : productPictureVOs) {
            Integer pictureId = productPictureVO.getId();
            oldPictureIds.add(pictureId);
        }

        //再从DTO中取出传过来的图片id
        List<ProductPictureUpdateDTO> pictures = productUpdateDTO.getPictures();
        ArrayList<Integer> oldNewPictureIds = new ArrayList<>();
        for (ProductPictureUpdateDTO picture : pictures) {
            Integer oldNewPictureId = picture.getId();
            oldNewPictureIds.add(oldNewPictureId);
        }

        //图片id集合去重，保留下来的即被删除的图片id
        oldPictureIds.removeAll(oldNewPictureIds);
        if (oldPictureIds.size() > 0) {
            log.info("产品图片关联表删除被删除的图片");
            assoProductPictureMapper.deleteByIds(oldPictureIds);
        }

        if (files != null && files.size() != 0) {
            ArrayList<AssoProductPicture> assoProductPictures = new ArrayList<>();
            for (MultipartFile file : files) {
                UploadFileDTO fileDTO = fileUtils.uploadFile(file);
                AssoProductPicture assoProductPicture = new AssoProductPicture()
                        .setProductId(productId)
                        .setName(fileDTO.getName())
                        .setSuffix(fileDTO.getExtName())
                        .setUrl(fileDTO.getPath());
                assoProductPictures.add(assoProductPicture);
            }

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

        }

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

    }

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

        PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
        productQueryPageDTO.setCreatePersonTenantId(personnelVO.getTenantId());

        Integer current = productQueryPageDTO.getCurrent();
        Integer size = productQueryPageDTO.getSize();
        String groupBy = productQueryPageDTO.getGroupBy();
        String orderBy = productQueryPageDTO.getOrderBy();
        if (orderBy != null) {
            String regex = "[A-Z]+";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(orderBy);
            while (matcher.find()) {
                orderBy = orderBy.replaceFirst(matcher.group(), "_" + matcher.group().toLowerCase());
            }
            productQueryPageDTO.setOrderBy(orderBy);
        }

        //根据 产品类别/公司 分组查询产品
        if (groupBy != null && !groupBy.equals("")) {
            if (current != null && size != null) {
                PageHelper.startPage(current, size);
            }
            List<ProductGroupVO> productGroupVOS;
            if (groupBy.equals("product_category_id")) {
                productGroupVOS = productMapper.queryByGroupProductCategoryId(productQueryPageDTO);
            } else {
                productGroupVOS = productMapper.queryByGroupCompanyName(productQueryPageDTO);
            }
            return JsonPage.restPage(new PageInfo<>(productGroupVOS));
        }

        //普通检索查询产品
        if (current != null && size != null) {
            PageHelper.startPage(current, size);
        }
        List<ProductVO> productVOs = productMapper.query(productQueryPageDTO);
        return JsonPage.restPage(new PageInfo<>(productVOs));

    }

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

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

        //检查专题库表中是否有该产品数据，若有则不允许删除
        log.info("检查专题库表中是否有该产品数据，若有则不允许删除");
        count = projectMapper.countByProductId(id);
        if (count > 0) {
            ThrowException.throwXiaoShiException("删除产品失败，该产品被专题库使用中，无法删除");
        }

        //删除产品架构专利专题库关联表数据
        log.info("产品架构专利专题库关联表删除数据");
        AssoStructurePatent assoStructurePatent = new AssoStructurePatent()
                .setProductId(id);
        assoStructurePatentMapper.delete(assoStructurePatent);

        //删除产品图片关联表数据
        log.info("产品图片关联表删除数据");
        assoProductPictureMapper.deleteByProductId(id);

        //删除产品专利关联表数据
        log.info("产品专利关联表删除数据");
        assoProductPatentMapper.deleteByProductId(id);

        //删除产品的所有架构的架构关联表数据和架构表数据
        LambdaQueryWrapper<Structure> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Structure::getProductId, id);
        ArrayList<Integer> structureIds = new ArrayList<>();
        List<Structure> structures = structureService.list(wrapper);
        if (structures != null && structures.size() > 0) {
            for (Structure structure : structures) {
                structureIds.add(structure.getId());
            }
            LambdaQueryWrapper<AssoStructurePicture> assoStructurePictureWrapper = new LambdaQueryWrapper<>();
            assoStructurePictureWrapper.in(AssoStructurePicture::getStructureId, structureIds);
            List<AssoStructurePicture> assoStructurePictures = assoStructurePictureService.list(assoStructurePictureWrapper);
            if (assoStructurePictures != null && assoStructurePictures.size() > 0) {
                log.info("架构图片关联表删除数据");
                //删除架构图片关联表数据
                assoStructurePictureService.remove(assoStructurePictureWrapper);
            }
            log.info("产品的架构表删除数据");
            structureService.remove(wrapper);
        }

        //删除产品营销数据
        LambdaQueryWrapper<ProductMarketData> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(ProductMarketData::getProductId, id);
        log.info("产品的营销数据表删除数据");
        productMarketDataService.remove(wrapper2);

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

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

    }


}
