package com.fjhx.sale.service.ext.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.area.utils.CustomizeAreaUtil;
import com.fjhx.common.enums.CodingRuleEnum;
import com.fjhx.common.enums.FlowStatusEnum1;
import com.fjhx.common.service.coding.CodingRuleService;
import com.fjhx.common.utils.Assert;
import com.fjhx.common.utils.Utils;
import com.fjhx.customer.service.customer.CustomerService;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.sale.entity.ext.dto.ExtQuotationDto;
import com.fjhx.sale.entity.ext.dto.ExtQuotationProductBomDto;
import com.fjhx.sale.entity.ext.dto.ExtQuotationProductDto;
import com.fjhx.sale.entity.ext.dto.ExtQuotationSelectDto;
import com.fjhx.sale.entity.ext.po.ExtQuotation;
import com.fjhx.sale.entity.ext.po.ExtQuotationFollow;
import com.fjhx.sale.entity.ext.po.ExtQuotationProduct;
import com.fjhx.sale.entity.ext.po.ExtQuotationProductBom;
import com.fjhx.sale.entity.ext.vo.ExtQuotationProductBomVo;
import com.fjhx.sale.entity.ext.vo.ExtQuotationProductVo;
import com.fjhx.sale.entity.ext.vo.ExtQuotationVo;
import com.fjhx.sale.entity.sale.po.SaleQuotation;
import com.fjhx.sale.mapper.ext.ExtQuotationMapper;
import com.fjhx.sale.service.ext.ExtQuotationFollowService;
import com.fjhx.sale.service.ext.ExtQuotationProductBomService;
import com.fjhx.sale.service.ext.ExtQuotationProductService;
import com.fjhx.sale.service.ext.ExtQuotationService;
import com.fjhx.sale.service.sale.SaleQuotationService;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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


/**
 * <p>
 * 对外报价单 服务实现类
 * </p>
 *
 * @author
 * @since 2024-01-14
 */
@Service
public class ExtQuotationServiceImpl extends ServiceImpl<ExtQuotationMapper, ExtQuotation> implements ExtQuotationService {

    @Autowired
    private CustomerService customerService;
    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private ExtQuotationProductService extQuotationProductService;
    @Autowired
    private ExtQuotationProductBomService extQuotationProductBomService;
    @Autowired
    private ExtQuotationFollowService extQuotationFollowService;
    @Autowired
    private SaleQuotationService saleQuotationService;
    @Autowired
    private CodingRuleService codingRuleService;
    @Autowired
    private ISysUserService sysUserService;

    @Override
    public Page<ExtQuotationVo> getPage(ExtQuotationSelectDto dto) {
        IWrapper<ExtQuotation> wrapper = getWrapper();

        //报价状态
        wrapper.eq(SaleQuotation::getQuotationStatus, dto.getQuotationStatus());
        //报价公司
        wrapper.eq(SaleQuotation::getCompanyId, dto.getCompanyId());
        //报价单类型
        wrapper.eq(SaleQuotation::getType, dto.getType());

        //报价时间-时间范围过滤
        wrapper.ge("eq", ExtQuotation::getQuotationTime, dto.getQuotationTimeSta());
        wrapper.le("eq", ExtQuotation::getQuotationTime, dto.getQuotationTimeEnd());
        //创建时间-时间范围过滤
        wrapper.ge("eq", ExtQuotation::getCreateTime, dto.getBeginTime());
        wrapper.le("eq", ExtQuotation::getCreateTime, dto.getEndTime());

        wrapper.ne("eq", ExtQuotation::getStatus, FlowStatusEnum1.UPDATE.getKey());
        wrapper.eq("eq", ExtQuotation::getStatus, dto.getStatus());

        //关键字过滤
        String keyword = dto.getKeyword();
        if (ObjectUtil.isNotEmpty(keyword)) {
            List<SysUser> userList = sysUserService.list(Wrappers.<SysUser>query().like("nick_name", dto.getKeyword()));
            List<Long> userIds = userList.stream().map(SysUser::getUserId).collect(Collectors.toList());
            wrapper.and(q -> q
                    .like("eq", ExtQuotation::getCode, dto.getKeyword())
                    .or()
                    .in("eq", ExtQuotation::getCreateUser, userIds)
            );
        }

        //最近有跟进的数据
        wrapper.le("DATEDIFF( NOW(), last_follow_time )", dto.getFollowDay());

        wrapper.orderByDesc("eq", ExtQuotation::getId);

        Page<ExtQuotationVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<ExtQuotationVo> records = page.getRecords();

        if (ObjectUtil.isEmpty(records)) {
            return page;
        }

        //获取对内报价单号
        List<Long> internalIds = records.stream().map(ExtQuotation::getSaleQuotationId).collect(Collectors.toList());
        Map<Long, String> internalMap = saleQuotationService.mapKV(SaleQuotation::getId, SaleQuotation::getCode,
                q -> q.in(SaleQuotation::getId, internalIds));

        // 赋值用户名称
        UserUtil.assignmentNickName(records, BasePo::getCreateUser, ExtQuotationVo::setUserName);

        // 赋值买方公司名称(客户)
        customerService.attributeAssign(records, ExtQuotationVo::getBuyCorporationId, (item, customer) -> {
            item.setBuyCorporationName(customer.getName());
        });

        List<Long> companyIds = records.stream().map(ExtQuotation::getCompanyId).collect(Collectors.toList());
        List<SysDept> companyList = sysDeptService.list(Wrappers.<SysDept>query().in("dept_id", companyIds));
        Map<Long, String> companyMap = companyList.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));

        List<Long> ids = records.stream().map(ExtQuotationVo::getId).collect(Collectors.toList());
        List<ExtQuotationProduct> pList = extQuotationProductService.list(q -> q.in(ExtQuotationProduct::getSaleQuotationId, ids));
        List<ExtQuotationProductVo> quotationProductVos = BeanUtil.copyToList(pList, ExtQuotationProductVo.class);
        //赋值产品信息
        productInfoService.attributeAssign(quotationProductVos, ExtQuotationProductVo::getProductId, (item, productInfo) -> {
            item.setProductCode(productInfo.getCustomCode());
            item.setProductName(productInfo.getName());

            item.setProductLength(productInfo.getLength());
            item.setProductWidth(productInfo.getWidth());
            item.setProductWidth(productInfo.getHeight());
            item.setProductColor(productInfo.getColor());
        });
        Map<Long, List<ExtQuotationProductVo>> pMap = quotationProductVos.stream().collect(Collectors.groupingBy(ExtQuotationProduct::getSaleQuotationId));

        //获取跟进记录Map
        Map<Long, List<ExtQuotationFollow>> followMap = extQuotationFollowService.mapKGroup(ExtQuotationFollow::getQuotationId, q -> q
                .in(ExtQuotationFollow::getQuotationId, ids)
                .orderByDesc(ExtQuotationFollow::getFollowTime)
        );

        for (ExtQuotationVo esq : records) {
            //赋值报价公司名称
            esq.setCompanyName(companyMap.get(esq.getCompanyId()));

            //赋值产品列表
            esq.setQuotationProductList(pMap.get(esq.getId()));

            //赋值跟进信息
            List<ExtQuotationFollow> extQuotationFollows = followMap.get(esq.getId());
            esq.setExtQuotationFollowList(extQuotationFollows);

            //赋值内部报价单号
            esq.setInternalCode(internalMap.get(esq.getSaleQuotationId()));
        }

        return page;
    }

    @Override
    public ExtQuotationVo detail(Long id) {
        //查询报价表详情
        ExtQuotation extQuotation = this.getById(id);
        ExtQuotationVo result = BeanUtil.toBean(extQuotation, ExtQuotationVo.class);
        if (ObjectUtil.isEmpty(result)) {
            throw new ServiceException("查询不到明细信息请检查");
        }

        //获取归属公司信息
        SysDept sysDept = sysDeptService.getById(result.getCompanyId());
        if (ObjectUtil.isNotEmpty(sysDept)) {
            result.setCompanyName(sysDept.getDeptName());
        }

        return setDetailInfo(Arrays.asList(result)).get(0);
    }

    @Override
    @DSTransactional
    public void add(ExtQuotationDto saleQuotationDto) {
        Long saleQuotationId = saleQuotationDto.getSaleQuotationId();
        SaleQuotation saleQuotation = saleQuotationService.getById(saleQuotationId);
        Assert.notEmpty(saleQuotation, "查询不到对内报价单信息请检查");

        //添加报价编码
        if (ObjectUtil.isEmpty(saleQuotationDto.getCode())) {
            saleQuotationDto.setCode(codingRuleService.createCode(CodingRuleEnum.EXT_SALE_QUOTATION.getKey(), saleQuotationDto.getBuyCorporationId()));
        }

        long id = IdWorker.getId();
        saleQuotationDto.setId(id);
        saleQuotationDto.setGroupId(id);//赋值数据分组id
        saleQuotationDto.setStatus(30);
        saveOrEdit(saleQuotationDto);

        //将对内报价单标记为转对外
        saleQuotationService.update(q -> q
                .eq(SaleQuotation::getId, saleQuotationId)
                .set(SaleQuotation::getExtQuotationId, saleQuotationDto.getId())
        );
    }

    @Override
    @DSTransactional
    public void edit(ExtQuotationDto saleQuotationDto) {
        if (Objects.equals(saleQuotationDto.getQuotationStatus(), 2)) {
            saleQuotationDto.setQuotationTime(new Date());
        }
        saveOrEdit(saleQuotationDto);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    /**
     * 变更
     */
    @Override
    public void changeSaleQuotation(ExtQuotationDto saleQuotationDto) {
        ExtQuotation saleQuotation = this.getById(saleQuotationDto.getId());
        if (ObjectUtil.isEmpty(saleQuotation)) {
            throw new ServiceException("查询不到原报价单信息");
        }
        saleQuotation.setStatus(FlowStatusEnum1.UPDATE.getKey());
        this.updateById(saleQuotation);

        saleQuotationDto.setOldQuotationId(saleQuotation.getId());

        //变更清除id信息
        saleQuotationDto.setId(null);
        saleQuotationDto.setStatus(30);
        saleQuotationDto.setQuotationStatus(0);
        saleQuotationDto.setCode(Utils.getNewCode(saleQuotation.getCode()));//赋值新合同号
        List<ExtQuotationProductDto> quotationProductList = saleQuotationDto.getQuotationProductList();
        for (ExtQuotationProductDto quotationProductDto : quotationProductList) {
            quotationProductDto.setId(null);
            List<ExtQuotationProductBomDto> quotationProductBomList = quotationProductDto.getQuotationProductBomList();
            for (ExtQuotationProductBomDto quotationProductBomDto : quotationProductBomList) {
                quotationProductBomDto.setId(null);
            }
            quotationProductDto.setQuotationProductBomList(quotationProductBomList);
        }
        saleQuotationDto.setQuotationProductList(quotationProductList);
        //调用创建方法
        saveOrEdit(saleQuotationDto);
    }


    /**
     * 作废
     */
    @Override
    public void cancellation(Long id) {
        ExtQuotation saleQuotation = this.getById(id);
        saleQuotation.setStatus(FlowStatusEnum1.CANCELLATION.getKey());
        this.updateById(saleQuotation);

        //标记对内报价单为可转对外
        saleQuotationService.update(q -> q
                .eq(SaleQuotation::getId, saleQuotation.getSaleQuotationId())
                .set(SaleQuotation::getExtQuotationId, null)
        );
    }

    /**
     * 赋值买卖公司地址
     */
    private void setArea(ExtQuotationVo saleQuotationVo) {

        List<Long> areaIdList = Arrays.asList(
                saleQuotationVo.getBuyCountryId(),
                saleQuotationVo.getBuyProvinceId(),
                saleQuotationVo.getBuyCityId()
        );
        Map<Long, String> areaMap = CustomizeAreaUtil.getAreaMapByIds(areaIdList);
        saleQuotationVo.setBuyCountryName(areaMap.get(saleQuotationVo.getBuyCountryId()));
        saleQuotationVo.setBuyProvinceName(areaMap.get(saleQuotationVo.getBuyProvinceId()));
        saleQuotationVo.setBuyCityName(areaMap.get(saleQuotationVo.getBuyCityId()));
        saleQuotationVo.setBuyDetailedAddress(saleQuotationVo.getBuyAddress());
    }

    /**
     * 添加修改公共方法
     */
    private void saveOrEdit(ExtQuotationDto saleQuotationDto) {
        this.saveOrUpdate(saleQuotationDto);

        List<ExtQuotationProductDto> quotationProductList = saleQuotationDto.getQuotationProductList();
        for (ExtQuotationProductDto quotationProductDto : quotationProductList) {
            //手动创建id
            if (ObjectUtil.isEmpty(quotationProductDto.getId())) {
                quotationProductDto.setId(IdWorker.getId());
            }
            quotationProductDto.setSaleQuotationId(saleQuotationDto.getId());

            //保存配件
            List<ExtQuotationProductBom> quotationProductBomList = BeanUtil.copyToList(quotationProductDto.getQuotationProductBomList(), ExtQuotationProductBom.class);
            for (ExtQuotationProductBom quotationProductBom : quotationProductBomList) {
                quotationProductBom.setProductId(quotationProductDto.getProductId());
                quotationProductBom.setQuotationProductId(quotationProductDto.getId());
            }
            extQuotationProductBomService.editLinked(quotationProductBomList, ExtQuotationProductBom::getQuotationProductId, quotationProductDto.getId());
        }

        List<ExtQuotationProduct> quotationProducts = BeanUtil.copyToList(quotationProductList, ExtQuotationProduct.class);
        extQuotationProductService.editLinked(quotationProducts, ExtQuotationProduct::getSaleQuotationId, saleQuotationDto.getId());
    }

    /**
     * 获取报价单历史版本
     */
    @Override
    public List<ExtQuotationVo> getVersionList(Long extQuotationId) {
        ExtQuotation extQuotation = this.getById(extQuotationId);
        Assert.notEmpty(extQuotation, "查询不到报价单信息！");
        Long groupId = extQuotation.getGroupId();
        List<ExtQuotation> extQuotationList = this.list(q -> q.eq(ExtQuotation::getGroupId, groupId).orderByDesc(ExtQuotation::getCreateTime));
        List<ExtQuotationVo> extQuotationVos = BeanUtil.copyToList(extQuotationList, ExtQuotationVo.class);
        return setDetailInfo(extQuotationVos);
    }

    /**
     * 赋值明细信息
     */
    private List<ExtQuotationVo> setDetailInfo(List<ExtQuotationVo> extQuotationVos) {
        Long groupId = extQuotationVos.get(0).getGroupId();

        //获取id列表
        List<Long> ids = extQuotationVos.stream().map(ExtQuotation::getId).collect(Collectors.toList());
        //获取子产品列表
        List<ExtQuotationProduct> productList = extQuotationProductService.list(q -> q.in(ExtQuotationProduct::getSaleQuotationId, ids));
        List<ExtQuotationProductVo> quotationProductVos = BeanUtil.copyToList(productList, ExtQuotationProductVo.class);
        Map<Long, List<ExtQuotationProductVo>> productMap = quotationProductVos.stream().collect(Collectors.groupingBy(ExtQuotationProductVo::getSaleQuotationId));
        //赋值产品信息
        productInfoService.attributeAssign(quotationProductVos, ExtQuotationProductVo::getProductId, (item, productInfo) -> {
            item.setProductCode(productInfo.getCustomCode());
            item.setProductName(productInfo.getName());
            item.setProductLength(productInfo.getLength());
            item.setProductWidth(productInfo.getWidth());
            item.setProductHeight(productInfo.getHeight());
            item.setProductColor(productInfo.getColor());
        });
        //获取配件列表
        List<Long> qpIds = productList.stream().map(ExtQuotationProduct::getId).collect(Collectors.toList());
        Map<Long, List<ExtQuotationProductBomVo>> qpbMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(qpIds)) {
            List<ExtQuotationProductBom> bomList = extQuotationProductBomService.list(q -> q.in(ExtQuotationProductBom::getQuotationProductId, qpIds));
            List<ExtQuotationProductBomVo> quotationProductBomVos = BeanUtil.copyToList(bomList, ExtQuotationProductBomVo.class);
            //赋值产品信息
            productInfoService.attributeAssign(quotationProductBomVos, ExtQuotationProductBom::getMaterialId, (item, productInfo) -> {
                item.setProductCode(productInfo.getCustomCode());
                item.setProductName(productInfo.getName());
                item.setProductLength(productInfo.getLength());
                item.setProductWidth(productInfo.getWidth());
                item.setProductHeight(productInfo.getHeight());
                item.setProductColor(productInfo.getColor());
            });
            qpbMap = quotationProductBomVos.stream().collect(Collectors.groupingBy(ExtQuotationProductBom::getQuotationProductId));
        }

        //赋值客户信息
        customerService.attributeAssign(extQuotationVos, ExtQuotation::getBuyCorporationId, (item, customer) -> {
            item.setBuyCorporationName(customer.getName());
        });

        //获取地址信息
        List<Long> areaIdList = new ArrayList<>();
        for (ExtQuotation quotation : extQuotationVos) {
            areaIdList.add(quotation.getBuyCountryId());
            areaIdList.add(quotation.getBuyProvinceId());
            areaIdList.add(quotation.getBuyCityId());
        }
        areaIdList = areaIdList.stream().distinct().collect(Collectors.toList());
        Map<Long, String> areaMap = CustomizeAreaUtil.getAreaMapByIds(areaIdList);

        //获取报价金额趋势
        List<ExtQuotation> quotationTrendList = this.list(q -> q
                .eq(ExtQuotation::getGroupId, groupId)
                .ne(ExtQuotation::getStatus, FlowStatusEnum1.CANCELLATION.getKey())
                .orderByAsc(ExtQuotation::getCreateTime)
        );

        //赋值信息
        for (ExtQuotationVo quotation : extQuotationVos) {
            //赋值买方地址
            quotation.setBuyCountryName(areaMap.get(quotation.getBuyCountryId()));
            quotation.setBuyProvinceName(areaMap.get(quotation.getBuyProvinceId()));
            quotation.setBuyCityName(areaMap.get(quotation.getBuyCityId()));
            quotation.setBuyDetailedAddress(quotation.getBuyAddress());

            //赋值产品列表
            List<ExtQuotationProductVo> quotationProductVos1 = productMap.getOrDefault(quotation.getId(), new ArrayList<>());
            for (ExtQuotationProductVo quotationProductVo : quotationProductVos1) {
                //赋值配件列表
                quotationProductVo.setQuotationProductBomList(qpbMap.get(quotationProductVo.getId()));
            }
            quotation.setQuotationProductList(quotationProductVos1);

            //获取报价金额趋势
            quotation.setQuotationTrendList(quotationTrendList);
        }

        return extQuotationVos;

    }

}
