package com.scm.contract.service.management;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.scm.contract.dao.management.MaterielDao;
import com.scm.contract.model.apply.DictionaryTagType;
import com.scm.contract.model.apply.LabelApplicationDataImport;
import com.scm.contract.model.management.Materiel;
import com.scm.contract.model.management.MaterielCategory;
import com.scm.contract.model.management.Provider;
import com.scm.contract.service.apply.DictionaryTagTypeService;
import com.set.direwolf.core.mybatis.CrudService;
import com.set.direwolf.core.mybatis.Page;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

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

import static com.scm.contract.tools.QcExcelUtil.*;

/**
 * @author zuo
 * @date 2024/6/13 14:03
 */
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class MaterielService extends CrudService<MaterielDao, Materiel, String> {

    @Autowired
    private DictionaryTagTypeService tagTypeService;

    @Autowired
    private MaterielCategoryService categoryService;

    @Autowired
    private ProviderService providerService;

    public List<Materiel> findList(Materiel materiel) {
        return this.dao.findList(materiel);
    }

    public List<Materiel> listByIds(List<String> ids) {
        return this.dao.listByIds(ids);
    }

    @Override
    public Page<Materiel> findPage(Page<Materiel> page, Materiel entity) {
        entity.setPage(page);
        Page<Materiel> materielPage = page.setList(this.dao.findList(entity));
        List<Materiel> materiels = materielPage.getList();
//        List<String> tagTypeIds = materiels.stream().map(Materiel::getTagTypeId).distinct().collect(Collectors.toList());
        Set<String> providerIds = new HashSet<>();
        Set<String> tagTypeIds = new HashSet<>();
        Set<String> categoryIds = new HashSet<>();
        for (Materiel materiel : materiels) {
            providerIds.add(materiel.getProviderId());
            tagTypeIds.add(materiel.getTagTypeId());
            categoryIds.add(materiel.getBigCategoryId());
            categoryIds.add(materiel.getMiddleCategoryId());
            categoryIds.add(materiel.getSmallCategoryId());
        }
        Map<String, Provider> providerMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(tagTypeIds)) {
            List<Provider> providers = providerService.listByIds(new ArrayList<>(providerIds));
            for (Provider provider : providers) {
                providerMap.put(provider.getId(),provider);
            }
        }
        Map<String, DictionaryTagType> tagTypeMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(tagTypeIds)) {
            List<DictionaryTagType> tagTypes = tagTypeService.listByIds(new ArrayList<>(tagTypeIds));
            for (DictionaryTagType tagType : tagTypes) {
                tagTypeMap.put(tagType.getId(), tagType);
            }

        }
        Map<String, MaterielCategory> categoryMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(categoryIds)) {
            List<MaterielCategory> materielCategories = categoryService.listByIds(new ArrayList<>(categoryIds));
            for (MaterielCategory category : materielCategories) {
                categoryMap.put(category.getId(), category);
            }
        }
        for (Materiel materiel : materiels) {
            String tagTypeId = materiel.getTagTypeId();
            DictionaryTagType tagType = tagTypeMap.getOrDefault(tagTypeId, new DictionaryTagType());
            materiel.setTagTypeName(tagType.getName());

            String bigCategoryId = materiel.getBigCategoryId();
            String middleCategoryId = materiel.getMiddleCategoryId();
            String smallCategoryId = materiel.getSmallCategoryId();
            String providerId = materiel.getProviderId();
            materiel.setBigCategoryName(categoryMap.getOrDefault(bigCategoryId, new MaterielCategory()).getName());
            materiel.setMiddleCategoryName(categoryMap.getOrDefault(middleCategoryId, new MaterielCategory()).getName());
            materiel.setSmallCategoryName(categoryMap.getOrDefault(smallCategoryId, new MaterielCategory()).getName());
            materiel.setProviderName(providerMap.getOrDefault(providerId, new Provider()).getName());
        }
        return materielPage;
    }

    public Workbook getTemplate() {
        List<Materiel> materiels = this.dao.findList(new Materiel());
        if (CollectionUtils.isNotEmpty(materiels)) {
            Set<String> tagTypeIds = new HashSet<>();
            Set<String> categoryIds = new HashSet<>();
            for (Materiel materiel : materiels) {
                categoryIds.add(materiel.getSmallCategoryId());
                tagTypeIds.add(materiel.getTagTypeId());
            }
            Map<String, DictionaryTagType> tagTypeMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(tagTypeIds)) {
                List<DictionaryTagType> tagTypes = tagTypeService.listByIds(new ArrayList<>(tagTypeIds));
                for (DictionaryTagType tagType : tagTypes) {
                    tagTypeMap.put(tagType.getId(), tagType);
                }

            }
            Map<String, MaterielCategory> categoryMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(categoryIds)) {
                List<MaterielCategory> materielCategories = categoryService.listByIds(new ArrayList<>(categoryIds));
                for (MaterielCategory category : materielCategories) {
                    categoryMap.put(category.getId(), category);
                }
            }
            for (Materiel materiel : materiels) {
                String tagTypeId = materiel.getTagTypeId();
                DictionaryTagType tagType = tagTypeMap.getOrDefault(tagTypeId, new DictionaryTagType());
                materiel.setTagTypeName(tagType.getName());
                String smallCategoryId = materiel.getSmallCategoryId();
                materiel.setSmallCategoryName(categoryMap.getOrDefault(smallCategoryId, new MaterielCategory()).getName());
            }
        }


        //在内存中保留100行，超过的行将刷新到磁盘
        Workbook wb = new XSSFWorkbook();
        //设置sheet
        Sheet sh = wb.createSheet("Sheet1");
        // 设置 excel 的默认宽度为12个字符的宽度
        sh.setDefaultColumnWidth(12);
        sh.setColumnWidth(2, 50 * 256);
        sh.setColumnWidth(3, 30 * 256);
        sh.setColumnWidth(4, 30 * 256);
        //创建样式对象
        CellStyle styleHeadlLock = getStyle(wb);
        styleHeadlLock.setLocked(true);
        styleHeadlLock.setWrapText(true);
        CellStyle styleHeadLock1 = getStyle(wb);
        styleHeadLock1.setLocked(true);
        styleHeadLock1.setWrapText(true);
        Font font = wb.createFont();
        font.setFontName("等线");
        font.setBold(true);
        font.setColor(Font.COLOR_RED);
        styleHeadLock1.setFont(font);
        CellStyle styleLock = getStyle2(wb);
        styleLock.setLocked(true);
        CellStyle styleDateLock = getStyle2(wb);
        styleDateLock.setLocked(true);
        styleDateLock.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat("yyyy/MM/dd"));
        CellStyle style = getStyle2(wb);
        style.setLocked(false);
        CellStyle styleDate = getStyle2(wb);
        styleDate.setLocked(false);
        styleDate.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat("yyyy/MM/dd"));
        sh.setColumnHidden(5, true);
        int rowNumb = 0;
        sh.protectSheet("more123");
        /**
         * 表头
         */
        Row row0 = sh.createRow(rowNumb++);
        setCell(row0, 0, "物料编码", styleHeadlLock);
        setCell(row0, 1, "商品编码", styleHeadlLock);
        setCell(row0, 2, "商品名称", styleHeadlLock);
        setCell(row0, 3, "物料小类", styleHeadlLock);
        setCell(row0, 4, "标签类型（请选择）", styleHeadLock1);
        setCell(row0, 5, "物料id（请勿需修改）", styleHeadLock1);

        for (Materiel materiel1 : materiels) {
            String materielCode = materiel1.getMaterielCode();
            String goodsCode = materiel1.getGoodsCode();
            String smallCategoryName = materiel1.getSmallCategoryName();
            String tagTypeName = materiel1.getTagTypeName();
            String name = materiel1.getGoodsName();
            String id = materiel1.getId();
            Row row = sh.createRow(rowNumb++);

            setCell(row, 0, materielCode, styleLock);
            setCell(row, 1, goodsCode, styleLock);
            setCell(row, 2, name, styleLock);
            setCell(row, 3, smallCategoryName, styleLock);
            setCell(row, 4, tagTypeName, style);
            setCell(row, 5, id, styleLock);
        }
        List<DictionaryTagType> tagTypes = tagTypeService.list();

        if (materiels.size() > 0) {
            // 创建下拉选择框的选项列表
            String[] tagTypeNames = tagTypes.stream().map(DictionaryTagType::getName).toArray(String[]::new);

            // 设置数据有效性（下拉选择框）
            DataValidationHelper helper = sh.getDataValidationHelper();
            DataValidationConstraint constraint = helper.createExplicitListConstraint(tagTypeNames);
            CellRangeAddressList addressList = new CellRangeAddressList(1, materiels.size(), 4, 4); // 第一列第1到100行
            DataValidation dataValidation = helper.createValidation(constraint, addressList);
            dataValidation.createErrorBox("Error", "You must select a valid option!");
            dataValidation.setShowErrorBox(true);
            sh.addValidationData(dataValidation);
        }
        return wb;

    }


    @Transactional
    public synchronized void importData(LabelApplicationDataImport dataImport) {
        Map<String, DictionaryTagType> tagTypeMap = new HashMap<>();
        List<DictionaryTagType> tagTypes = tagTypeService.list();
        for (DictionaryTagType tagType : tagTypes) {
            tagTypeMap.put(tagType.getName(), tagType);
        }
        MultipartFile file = dataImport.getFile();

        List<Materiel> materiels = new ArrayList<>();
        try {
            int totalRowNum = 0;
//            Workbook workbook = WorkbookFactory.create(fileInputStream, password);
            XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
            XSSFSheet sheet = workbook.getSheetAt(0);
            if (Objects.isNull(sheet)) throw new RuntimeException("空表,不能进行导入");
            totalRowNum = sheet.getLastRowNum();
            XSSFRow headRow = sheet.getRow(0);
            if (Objects.isNull(headRow)) throw new RuntimeException("空表,不能进行导入");

            for (int i = 1; i <= totalRowNum; i++) {
                XSSFRow row = sheet.getRow(i);
                Materiel materiel = new Materiel();
                //标签数量
                XSSFCell cell5 = row.getCell(5);
                String cell5Value = cell5.getStringCellValue();
                if (StringUtils.isNotBlank(cell5Value)) {
                    XSSFCell cell4 = row.getCell(4);
                    String cell4Value = cell4.getStringCellValue();
                    if (StringUtils.isNotBlank(cell4Value)) {
                        DictionaryTagType tagType = tagTypeMap.get(cell4Value);
                        if (!Objects.isNull(tagType)) {
                            materiel.setId(cell5Value);
                            materiel.setTagTypeId(tagType.getId());
                            materiels.add(materiel);
                        }
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if (CollectionUtils.isNotEmpty(materiels)) {
            Boolean b = this.dao.updateTagType(materiels);
        }
    }

    public Materiel getById(String id) {
        Materiel materiel = this.dao.getById(id);
        if (!Objects.isNull(materiel)){
            Set<String> tagTypeIds = new HashSet<>();
            Set<String> categoryIds = new HashSet<>();
            tagTypeIds.add(materiel.getTagTypeId());
            categoryIds.add(materiel.getBigCategoryId());
            categoryIds.add(materiel.getMiddleCategoryId());
            categoryIds.add(materiel.getSmallCategoryId());

            Map<String, DictionaryTagType> tagTypeMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(tagTypeIds)) {
                List<DictionaryTagType> tagTypes = tagTypeService.listByIds(new ArrayList<>(tagTypeIds));
                for (DictionaryTagType tagType : tagTypes) {
                    tagTypeMap.put(tagType.getId(), tagType);
                }
            }

            Map<String, MaterielCategory> categoryMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(categoryIds)) {
                List<MaterielCategory> materielCategories = categoryService.listByIds(new ArrayList<>(categoryIds));
                for (MaterielCategory category : materielCategories) {
                    categoryMap.put(category.getId(), category);
                }
            }
            String tagTypeId = materiel.getTagTypeId();
            DictionaryTagType tagType = tagTypeMap.getOrDefault(tagTypeId, new DictionaryTagType());
            materiel.setTagTypeName(tagType.getName());

            String bigCategoryId = materiel.getBigCategoryId();
            String middleCategoryId = materiel.getMiddleCategoryId();
            String smallCategoryId = materiel.getSmallCategoryId();
            materiel.setBigCategoryName(categoryMap.getOrDefault(bigCategoryId, new MaterielCategory()).getName());
            materiel.setMiddleCategoryName(categoryMap.getOrDefault(middleCategoryId, new MaterielCategory()).getName());
            materiel.setSmallCategoryName(categoryMap.getOrDefault(smallCategoryId, new MaterielCategory()).getName());
        }
        return materiel;
    }
}
