package com.jwipc.tender.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.jwipc.aggregation.ModelAggregationService;
import com.jwipc.constant.DictCode;
import com.jwipc.constant.FlagConst;
import com.jwipc.dto.ExportDataDTO;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import com.jwipc.sys.client.DictClient;
import com.jwipc.sys.client.ProductClient;
import com.jwipc.sys.client.dto.ProductInfoDTO;
import com.jwipc.tender.constant.BargainingStatus;
import com.jwipc.tender.constant.DimensionCode;
import com.jwipc.tender.constant.SupplierMaterialFlag;
import com.jwipc.tender.convert.*;
import com.jwipc.tender.dto.*;
import com.jwipc.tender.entity.*;
import com.jwipc.tender.logic.TenderTemplateLogic;
import com.jwipc.tender.model.query.TenderTemplateQuery;
import com.jwipc.tender.service.*;
import com.jwipc.util.DateUtils;
import com.jwipc.util.EasyExcelUtils;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p> </p>
 *
 * @author BOGON
 * @version 1.0
 * @since JDK 1.8
 */
@Service
@RequiredArgsConstructor
public class TenderTemplateLogicImpl implements TenderTemplateLogic {
    private final ITenderTemplateService tenderTemplateService;
    private final ITenderTemplateFieldRefService tenderTemplateFieldRefService;
    private final TenderTemplateFieldRefConvert tenderTemplateFieldRefConvert;
    private final ITenderTemplateFieldService tenderTemplateFieldService;
    private final TenderTemplateFieldConvert tenderTemplateFieldConvert;
    private final TenderTemplateConvert tenderTemplateConvert;
    private final ITenderService tenderService;
    private final IDimensionService dimensionService;
    private final DimensionConvert dimensionConvert;
    private final ModelAggregationService modelAggregationService;
    private final ITenderBidService bidService;
    private final ITenderBidDetailService tenderBidDetailService;
    private final ITenderBidDetailExtService tenderBidDetailExtService;
    private final TenderBidDetailConvert tenderBidDetailConvert;
    private final ProductClient productClient;
    private final ITenderRoundService tenderRoundService;
    private final DictClient dictClient;


    /**
     * 获取列表
     *
     * @param query 查询条件
     * @return 列表
     */
    @Override
    public PageView getList(TenderTemplateQuery query) {
        final Page<TenderTemplate> page = PageUtil.toPage(query);
        final LambdaQueryWrapper<TenderTemplate> wrapper = new LambdaQueryWrapper<TenderTemplate>()
                .like(StrUtil.isNotEmpty(query.getCode()), TenderTemplate::getCode, SqlUtils.concatLike(query.getCode(),
                        SqlLike.DEFAULT))
                .like(StrUtil.isNotEmpty(query.getName()), TenderTemplate::getName, SqlUtils.concatLike(query.getName(),
                        SqlLike.DEFAULT));
        final List<TenderTemplate> list = tenderTemplateService.list(page, wrapper);
        List<TenderTemplateBaseDTO> tenderTemplateBaseDTOS = tenderTemplateConvert.entities2Dtos(list);
        modelAggregationService.processRelationAggregation(tenderTemplateBaseDTOS);
        return PageUtil.getPV(tenderTemplateBaseDTOS, page.getTotal());
    }

    @Override
    public TenderTemplateBaseDTO getDetail(Long id) {
        final TenderTemplate byId = tenderTemplateService.getById(id);
        if (Objects.isNull(byId)) {
            return new TenderTemplateBaseDTO();
        }
        return tenderTemplateConvert.entity2Dto(byId);
    }

    @Override
    public List<TenderTemplateFieldBaseDTO> getTemplateFieldList(Long id) {
        if (id == 0L) {
            //查询默认的字段
            final List<TenderTemplateField> list = tenderTemplateFieldService.list(
                    new LambdaQueryWrapper<TenderTemplateField>().eq(TenderTemplateField::getDefaultFlag,
                            FlagConst.Y.getCode()));
            //需要把id转移到fieldId
            final List<TenderTemplateFieldBaseDTO> tenderTemplateFieldBaseDTOS =
                    tenderTemplateFieldConvert.entities2Dtos(
                            list);
            for (TenderTemplateFieldBaseDTO tenderTemplateFieldBaseDTO : tenderTemplateFieldBaseDTOS) {
                tenderTemplateFieldBaseDTO.setFieldId(tenderTemplateFieldBaseDTO.getId());
                tenderTemplateFieldBaseDTO.setId(null);
            }
            return tenderTemplateFieldBaseDTOS;
        } else {
            final List<TenderTemplateFieldRef> list = tenderTemplateFieldRefService.list(
                    new LambdaQueryWrapper<TenderTemplateFieldRef>().eq(TenderTemplateFieldRef::getTemplateId, id)
                            .orderByAsc(TenderTemplateFieldRef::getFieldSort));
            //查询字段主表数据
            final List<Long> fieldIds = list.stream().map(TenderTemplateFieldRef::getFieldId)
                    .collect(Collectors.toList());
            Map<Long, TenderTemplateField> stringMap = Maps.newHashMap();
            if (CollUtil.isNotEmpty(fieldIds)) {
                final List<TenderTemplateField> fields = tenderTemplateFieldService.list(
                        new LambdaQueryWrapper<TenderTemplateField>().in(TenderTemplateField::getId, fieldIds));
                stringMap = fields.stream()
                        .collect(Collectors.toMap(TenderTemplateField::getId, a -> a));
            }
            final List<TenderTemplateFieldBaseDTO> tenderTemplateFieldBaseDTOS =
                    tenderTemplateFieldRefConvert.entities2Dtos(
                            list);
            for (TenderTemplateFieldBaseDTO tenderTemplateFieldBaseDTO : tenderTemplateFieldBaseDTOS) {
                final Long dtoId = tenderTemplateFieldBaseDTO.getFieldId();
                tenderTemplateFieldBaseDTO.setLabelName(stringMap.get(dtoId).getLabelName());
                tenderTemplateFieldBaseDTO.setFieldName(stringMap.get(dtoId).getFieldName());
                tenderTemplateFieldBaseDTO.setFieldType(stringMap.get(dtoId).getFieldType());
                tenderTemplateFieldBaseDTO.setExtVal(stringMap.get(dtoId).getExtVal());
            }
            return tenderTemplateFieldBaseDTOS;

        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(TenderTemplateSaveDTO saveDTO) {
        TenderTemplate tenderTemplate = tenderTemplateConvert.dto2Entity(saveDTO);
        final TenderTemplate dbTemplate = tenderTemplateService.getById(tenderTemplate.getId());
        if (Objects.nonNull(dbTemplate) && saveDTO.isCopyFlag()) {
            //复制
            tenderTemplate.setId(null);
            tenderTemplate.setCreateId(LoginUtil.getUserId());
            tenderTemplate.setCreateTime(LocalDateTime.now());
            tenderTemplateService.save(tenderTemplate);
        } else if (Objects.nonNull(dbTemplate)) {
            //修改
            tenderTemplate.setUpdateId(LoginUtil.getUserId());
            tenderTemplate.setUpdateTime(LocalDateTime.now());
            tenderTemplateService.updateById(tenderTemplate);
            //需要删除字段关联
            tenderTemplateFieldRefService.remove(
                    new LambdaQueryWrapper<TenderTemplateFieldRef>().eq(TenderTemplateFieldRef::getTemplateId,
                            tenderTemplate.getId()));
        } else {
            //新增
            tenderTemplate.setCreateId(LoginUtil.getUserId());
            tenderTemplate.setCreateTime(LocalDateTime.now());
            tenderTemplateService.save(tenderTemplate);
        }
        final List<TenderTemplateFieldRefBaseDTO> fields = saveDTO.getFields();
        List<TenderTemplateFieldRef> insertLists = tenderTemplateFieldRefConvert.dtos2Entities(fields);
        for (TenderTemplateFieldRef insertList : insertLists) {
            insertList.setTemplateId(tenderTemplate.getId());
        }
        if (CollUtil.isNotEmpty(insertLists)) {
            tenderTemplateFieldRefService.saveBatch(insertLists);
        }
    }

    @Override
    public PageView getFieldList() {
        final List<TenderTemplateField> list = tenderTemplateFieldService.list();
        final List<TenderTemplateFieldBaseDTO> tenderTemplateFieldBaseDTOS = tenderTemplateFieldConvert.entities2Dtos(
                list);
        return PageUtil.getPV(tenderTemplateFieldBaseDTOS, tenderTemplateFieldBaseDTOS.size());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Long id) {
        tenderTemplateService.removeById(id);
        tenderTemplateFieldRefService.remove(
                new LambdaQueryWrapper<TenderTemplateFieldRef>().eq(TenderTemplateFieldRef::getTemplateId, id));

    }

    @Override
    public List<TenderTemplateBaseDTO> getListAll(Long typeId) {
        final List<TenderTemplate> list = tenderTemplateService.list(new LambdaQueryWrapper<TenderTemplate>()
                .eq(typeId != 0L, TenderTemplate::getTenderTypeId, typeId));
        return tenderTemplateConvert.entities2Dtos(list);
    }

    @Override
    public BenchmarksFieldDTO getTenderFields(Long id) {
        final Tender tender = tenderService.getById(id);
        if (Objects.isNull(tender)) {
            throw new DaoException("招标单不存在!");
        }
        List<TenderTemplateFieldBaseDTO> fieldList = this.getTemplateFieldList(tender.getTemplateId());
        fieldList = fieldList.stream().filter(a -> a.getBenchmarkingShow().equals(FlagConst.Y.getCode())).toList();
        BenchmarksFieldDTO benchmarksFieldDTO = new BenchmarksFieldDTO();
        benchmarksFieldDTO.setFields(fieldList);
        //需要判断是否需要评分
        List<DimensionDTO> dimensionDTOS = Lists.newArrayList();
        final TenderRound tenderRound = tenderRoundService.getOne(
                new LambdaQueryWrapper<>(TenderRound.class).eq(TenderRound::getTenderId, id), false);
        if (tenderRound.getScoreFlag().equals(FlagConst.Y.getCode())) {
            final List<Dimension> list = dimensionService.list();
            dimensionDTOS = dimensionConvert.entity2ListDTO(list);
            //需要增加总分字段
            final DimensionDTO totalDimension = new DimensionDTO();
            totalDimension.setCode(DimensionCode.DC_TOTAL.getCode());
            totalDimension.setName(DimensionCode.DC_TOTAL.getName());
            dimensionDTOS.add(totalDimension);
        }
        benchmarksFieldDTO.setDc(dimensionDTOS);
        return benchmarksFieldDTO;
    }

    @Override
    public void tempExport(HttpServletResponse response, Long templateId, Integer thresholdFlag) throws IOException {
        final List<TenderTemplateFieldBaseDTO> templateFieldList = getTemplateFieldList(templateId);
        List<ExportDataDTO> exportDataDTOS = new ArrayList<>();
        if (Objects.equals(thresholdFlag, FlagConst.Y.getCode())) {
            //如果需要阈值，则添加阈值字段
            final ExportDataDTO.ExportDataDTOBuilder builder = ExportDataDTO.builder()
                    .field("door_price");
            builder.title("*门槛价");
            exportDataDTOS.add(builder.build());
        }
        for (TenderTemplateFieldBaseDTO fieldBaseDTO : templateFieldList) {
            final String labelName = fieldBaseDTO.getLabelName();
            final String fieldAlias = fieldBaseDTO.getFieldAlias();
            //如果是采购填写需要颜色判断
            final Integer edit = fieldBaseDTO.getEdit();
            final Integer required = fieldBaseDTO.getRequired();
            String req = "";
            final ExportDataDTO.ExportDataDTOBuilder builder = ExportDataDTO.builder()
                    .field(fieldBaseDTO.getFieldName());
            if (Objects.equals(edit, FlagConst.Y.getCode())) {
                if (Objects.equals(required, FlagConst.Y.getCode())) {
                    req = "*";
                }
                builder.color(IndexedColors.YELLOW.getIndex());
            }
            builder.title(req + (StrUtil.isNotEmpty(fieldAlias) ? fieldAlias : labelName));
            exportDataDTOS.add(builder.build());
        }
        //动态导出工具类，只需要修改导出excel名称
        EasyExcelUtils.trendsModelWrite(response,
                "招标行模板-" + DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN), "sheet",
                Lists.newArrayList(), JSON.toJSONString(exportDataDTOS));
    }

    @Override
    public List<Map<String, String>> handleImportData(List<Map<String, String>> dataList) {
        List<Map<String, String>> result = Lists.newArrayList();
        Set<String> tipMsg = Sets.newHashSet();
        int i = 2;
        for (Map<String, String> stringStringMap : dataList) {
            i++;
            Map<String, String> map = new HashMap<>();
            for (String s : stringStringMap.keySet()) {
                map.put(StrUtil.toCamelCase(s), stringStringMap.get(s));
            }
            //需要查询物料
            final String materialCode = map.get("materialCode");
            final String factoryCode = map.get("factoryCode");
            if (StrUtil.isNotEmpty(materialCode)) {
                //需要查询物料信息
                if (StrUtil.isEmpty(factoryCode)) {
                    tipMsg.add(i + "行,工厂编码不存在");
                    continue;
                }
                final ProductInfoDTO productInfoDTO = productClient.getByMaterialCodeAndFactoryCode(
                        materialCode, factoryCode);
                if (Objects.isNull(productInfoDTO)) {
                    tipMsg.add(i + "行,物料不存在");
                } else {
                    final String materialName = productInfoDTO.getMaterialName();
                    final String groupName = productInfoDTO.getMaterialGroupName();
                    final String groupCode = productInfoDTO.getMaterialGroupCode();
                    final String unit = productInfoDTO.getOrderUnit();
                    final String materialDesc = productInfoDTO.getMaterialDesc();
                    map.put("materialName", materialName);
                    map.put("materialDesc", materialDesc);
                    map.put("materialGroupCode", groupCode);
                    map.put("unit", unit);
                    map.put("materialGroupName", groupName);

                }
            } else {
                map.put("materialDesc", map.get("materialName"));
            }
            if (Objects.isNull(map.get("priceStartDate"))) {
                map.put("priceStartDate", DateUtils.formatYYYYMMDDDash(LocalDate.now()));
            }
            if (Objects.isNull(map.get("priceValidityDate"))) {
                map.put("priceValidityDate", DateUtils.formatYYYYMMDDDash(LocalDate.now().plusYears(1)));
            }
            result.add(map);
        }
        if (CollUtil.isNotEmpty(tipMsg)) {
            throw new DaoException(tipMsg.stream().collect(Collectors.joining("</br>")));
        }
        return result;
    }

    @Override
    public void export1(HttpServletResponse response, Long bidId, Long historyFlag, Integer thresholdFlag,
                        Integer bargaining) throws
            IOException
    {
        final TenderBid byId = bidService.getById(bidId);
        final Long tenderId = byId.getTenderId();
        final Tender tender = tenderService.getById(tenderId);
        final List<TenderTemplateFieldBaseDTO> fieldList = this.getTemplateFieldList(tender.getTemplateId()).stream()
                .filter(a -> a.getSupplierEdit().equals(FlagConst.Y.getCode()) ||
                        a.getSupplierShow().equals(FlagConst.Y.getCode())).toList();
        List<ExportDataDTO> exportDataDTOS = new ArrayList<>();
        final ExportDataDTO.ExportDataDTOBuilder id = ExportDataDTO.builder()
                .field("id");
        id.title("");
        exportDataDTOS.add(id.build());
        if (Objects.equals(thresholdFlag, FlagConst.Y.getCode())) {
            //如果需要阈值，则添加阈值字段
            final ExportDataDTO.ExportDataDTOBuilder builder = ExportDataDTO.builder()
                    .field("doorPrice");
            builder.title("*门槛价");
            exportDataDTOS.add(builder.build());
        }
        Map<String, Map<String, String>> dictCache = Maps.newHashMap();
        if (Objects.equals(bargaining, FlagConst.Y.getCode())) {
            //议价需要把议价的数据填充进来
            exportDataDTOS.add(ExportDataDTO.builder()
                    .field("bargaining").title("期望价").build());
            exportDataDTOS.add(ExportDataDTO.builder()
                    .field("bargainingRemark").title("议价备注").build());
            exportDataDTOS.add(ExportDataDTO.builder()
                    .field("bargainingSupplier").title("*回复价").color(IndexedColors.YELLOW.getIndex()).build());
            exportDataDTOS.add(ExportDataDTO.builder()
                    .field("bargainingSupplierRemark").color(IndexedColors.YELLOW.getIndex()).title("*回复议价备注")
                    .build());
        }
        if (historyFlag == 1) {
            //议价需要把议价的数据填充进来
            exportDataDTOS.add(ExportDataDTO.builder()
                    .field("statusStr").title("是否中标").build());
            exportDataDTOS.add(ExportDataDTO.builder()
                    .field("bargaining").title("期望价").build());
            exportDataDTOS.add(ExportDataDTO.builder()
                    .field("bargainingRemark").title("议价备注").build());
            exportDataDTOS.add(ExportDataDTO.builder()
                    .field("bargainingSupplier").title("回复价").build());
            exportDataDTOS.add(ExportDataDTO.builder()
                    .field("bargainingSupplierRemark").title("回复议价备注")
                    .build());
        }
        for (TenderTemplateFieldBaseDTO fieldBaseDTO : fieldList) {
            final String labelName = fieldBaseDTO.getLabelName();
            final String fieldAlias = fieldBaseDTO.getFieldAlias();
            //如果是采购填写需要颜色判断
            final Integer supplierEdit = fieldBaseDTO.getSupplierEdit();
            final Integer supplierShow = fieldBaseDTO.getSupplierShow();
            final Integer required = fieldBaseDTO.getRequired();
            String req = "";
            final String fieldName = fieldBaseDTO.getFieldName();
            final ExportDataDTO.ExportDataDTOBuilder builder = ExportDataDTO.builder()
                    .field(StrUtil.toCamelCase(fieldName));
            if (fieldName.equals("country_name") || fieldName.equals("msl")) {
                //需要获取字典
                final Map<String, String> cuntryDictCache = dictClient.getDicMapByType(fieldBaseDTO.getExtVal());
                dictCache.put(fieldName, cuntryDictCache);
                final List<String> list = cuntryDictCache.values().stream().toList();
                builder.selectList(list);
            }
            if (Objects.equals(supplierEdit, FlagConst.Y.getCode()) ) {
                if (Objects.equals(required, FlagConst.Y.getCode())) {
                    if(Objects.equals(bargaining, FlagConst.Y.getCode())&&fieldName.equals("tax_price")){

                    }else{
                        req = "*";
                    }
                }
                if (historyFlag != 1) {
                    if(Objects.equals(bargaining, FlagConst.Y.getCode())&&fieldName.equals("tax_price")){

                    }else{
                        builder.color(IndexedColors.YELLOW.getIndex());
                    }

                }
                //如果是议价需要把含税报价的颜色和*号去掉
                builder.title(req + (StrUtil.isNotEmpty(fieldAlias) ? fieldAlias : labelName));
                exportDataDTOS.add(builder.build());
            } else if (Objects.equals(supplierShow, FlagConst.Y.getCode())) {
                builder.title(req + (StrUtil.isNotEmpty(fieldAlias) ? fieldAlias : labelName));
                exportDataDTOS.add(builder.build());
            }
        }
        //处理投标明细
        final LambdaQueryWrapper<TenderBidDetail> queryWrapper = new LambdaQueryWrapper<TenderBidDetail>().eq(
                TenderBidDetail::getBidId, bidId);
        if (Objects.equals(bargaining, FlagConst.Y.getCode())) {
            queryWrapper.eq(TenderBidDetail::getBargainingStatus, BargainingStatus.BARGAINING.getValue());
        }
        final List<TenderBidDetail> list = tenderBidDetailService.list(
                queryWrapper);
        final Set<Long> detailIds = list.stream().map(TenderBidDetail::getId).collect(Collectors.toSet());
        //需要判断供应商描述,如果是短描述需要
        if (tender.getSupplierMaterialFlag().equals(SupplierMaterialFlag.SHORT_NAME.getCode())) {
            for (TenderBidDetail tenderDetailDTO : list) {
                tenderDetailDTO.setMaterialName(tenderDetailDTO.getMaterialDesc());
            }
        }
        final List<TenderBidDetailExt> detailExts = Lists.newArrayList();
        if (CollUtil.isNotEmpty(detailIds)) {
            detailExts.addAll(tenderBidDetailExtService.listByIds(detailIds));
        }

        final Map<Long, TenderBidDetailExt> extCache = detailExts.stream()
                .collect(Collectors.toMap(TenderBidDetailExt::getId, a -> a));
        List<TenderBidDetailAllDTO> tenderBidDetailAllDTOS = tenderBidDetailConvert.entities2AllDtos(list);
        for (TenderBidDetailAllDTO tenderBidDetailAllDTO : tenderBidDetailAllDTOS) {
            final TenderBidDetailExt tenderBidDetailExt = extCache.get(tenderBidDetailAllDTO.getId());
            if (tenderBidDetailAllDTO.getStatus() == 0) {
                tenderBidDetailAllDTO.setStatusStr("否");
            } else if (tenderBidDetailAllDTO.getStatus() == 1) {
                tenderBidDetailAllDTO.setStatusStr("是");
            }
            if (Objects.nonNull(tenderBidDetailExt)) {
                tenderBidDetailConvert.mergeToAllDtos(tenderBidDetailAllDTO, tenderBidDetailExt);
            }
            final String countryName = tenderBidDetailAllDTO.getCountryName();
            if (StrUtil.isNotEmpty(countryName)) {
                final Map<String, String> stringStringMap = dictCache.get("country_name");
                if (ObjectUtil.isNotEmpty(stringStringMap)){
                    final String s = stringStringMap.get(countryName);
                    if (StrUtil.isNotEmpty(s)) {
                        tenderBidDetailAllDTO.setCountryName(s);
                    }
                }
            }
        }
        String fileName = "投标数据-" + DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);
        if (Objects.equals(bargaining, FlagConst.Y.getCode())) {
            fileName = "议价数据-" + DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);
        }
        //动态导出工具类，只需要修改导出excel名称
        EasyExcelUtils.trendsModelWrite(response,
                fileName, "sheet",
                tenderBidDetailAllDTOS, JSON.toJSONString(exportDataDTOS));
    }

    @Override
    public List<Map<String, String>> handleImport1Data(List<Map<String, String>> dataList) {
        //导入需要处理
        final Map<String, String> cuntryDictCache = dictClient.getDicMapByTypeNameKey(
                DictCode.COUNTRY_SERIES.getCode());
        final Map<String, String> mslDictCache = dictClient.getDicMapByTypeNameKey(DictCode.MSL_LEVEL.getCode());
        for (Map<String, String> stringStringMap : dataList) {
            final String msl = stringStringMap.get("msl");
            if (StrUtil.isNotEmpty(msl)) {
                stringStringMap.put("msl", mslDictCache.get(msl));
            }
            final String countryName = stringStringMap.get("countryName");
            if (StrUtil.isNotEmpty(countryName)) {
                stringStringMap.put("countryName", cuntryDictCache.get(countryName));
            }

        }
        return dataList;
    }
}