package com.xkrs.service.impl;

import com.xkrs.dao.CraftItemDao;
import com.xkrs.dao.QcItemDao;
import com.xkrs.dao.QcSourceDao;
import com.xkrs.dao.QcSpecDao;
import com.xkrs.encapsulation.PromptMessageEnum;
import com.xkrs.model.bean.XSSFCellDataBean;
import com.xkrs.model.entity.CraftItemEntity;
import com.xkrs.model.entity.QcItemEntity;
import com.xkrs.model.entity.QcSourceEntity;
import com.xkrs.model.entity.QcSpecEntity;
import com.xkrs.model.qo.ExportSourceExcelQo;
import com.xkrs.model.qo.QcSourceQoDelete;
import com.xkrs.model.qo.QcSourceQoInsert;
import com.xkrs.service.QcSourceService;
import com.xkrs.util.*;
import org.apache.http.util.TextUtils;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.*;

import static com.xkrs.encapsulation.OutputEncapsulation.outputEncapsulationObject;

@Service
public class QcSourceServiceImpl implements QcSourceService {

    private Locale locale = LocaleContextHolder.getLocale();

    @Resource
    private CraftItemDao craftItemDao;

    @Resource
    private QcItemDao qcItemDao;

    @Resource
    private QcSourceDao qcSourceDao;

    @Resource
    private QcSpecDao qcSpecDao;

    /**
     * 导出excel样式一(表头顺序)
     * 批次号 机器号 物料号 模具号 机种号
     */
    List<String> EXCEL_HEAD_STYLE_ONE_NO = Arrays.asList("batchNo", "machineNo", "materialNo", "mouldNo", "varietyNo", "craftItemNo");
    List<String> EXCEL_HEAD_STYLE_ONE_NAME = Arrays.asList("批次", "机器", "物料", "模具", "机种", "工艺项目");

    /**
     * 添加检验数据
     */
    @Override
    public String insertQcSource(QcSourceQoInsert insertQo, MultipartFile picture) {
        String batchNo = insertQo.getBatchNo();
        String machineNo = insertQo.getMachineNo();
        String materialNo = insertQo.getMaterialNo();
        String mouldNo = insertQo.getMouldNo();
        String varietyNo = insertQo.getVarietyNo();
        String craftItemNo = insertQo.getCraftItemNo();
        String qcItemNo = insertQo.getQcItemNo();
        String qcValue = insertQo.getQcValue();
        Optional<CraftItemEntity> craftItemByNo = craftItemDao.findByCraftItemNo(craftItemNo);
        if (craftItemByNo.isEmpty()) {
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "不存在该工艺项目,请先添加工艺项目!", locale);
        }
        Optional<QcItemEntity> qcItemByNo = qcItemDao.findByQcItemNo(qcItemNo);
        if (qcItemByNo.isEmpty()) {
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "不存在该检验项目,请先添加检验项目!", locale);
        }
        if (Constant.QC_ITEM_TYPE_STRING.equals(qcItemByNo.get().getQcItemType())) {
            QcSourceEntity entity = new QcSourceEntity();
            entity.setCreateTime(LocalDateUtils.getCurrentSecond());
            entity.setBatchNo(LocalStringUtils.formatEmptyValue(batchNo));
            entity.setMachineNo(LocalStringUtils.formatEmptyValue(machineNo));
            entity.setMaterialNo(LocalStringUtils.formatEmptyValue(materialNo));
            entity.setMouldNo(LocalStringUtils.formatEmptyValue(mouldNo));
            entity.setVarietyNo(LocalStringUtils.formatEmptyValue(varietyNo));
            entity.setCraftItemNo(LocalStringUtils.formatEmptyValue(craftItemNo));
            entity.setQcItemNo(LocalStringUtils.formatEmptyValue(qcItemNo));
            entity.setQcValue(LocalStringUtils.formatEmptyValue(qcValue));
            qcSourceDao.save(entity);
            return outputEncapsulationObject(PromptMessageEnum.SUCCESS, "添加成功!", locale);
        }
        if (Constant.QC_ITEM_TYPE_PICTURE.equals(qcItemByNo.get().getQcItemType())) {
            if (picture == null) {
                return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "上传图片不能为空!", locale);
            }
            String picturePath;
            try {
                picturePath = ExcelUploadUtil.memoryFile(picture, 2);
            } catch (IOException e) {
                e.printStackTrace();
                return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "上传图片失败!", locale);
            }
            QcSourceEntity entity = new QcSourceEntity();
            entity.setCreateTime(LocalDateUtils.getCurrentSecond());
            entity.setBatchNo(LocalStringUtils.formatEmptyValue(batchNo));
            entity.setMachineNo(LocalStringUtils.formatEmptyValue(machineNo));
            entity.setMaterialNo(LocalStringUtils.formatEmptyValue(materialNo));
            entity.setMouldNo(LocalStringUtils.formatEmptyValue(mouldNo));
            entity.setVarietyNo(LocalStringUtils.formatEmptyValue(varietyNo));
            entity.setCraftItemNo(LocalStringUtils.formatEmptyValue(craftItemNo));
            entity.setQcItemNo(LocalStringUtils.formatEmptyValue(qcItemNo));
            entity.setQcValue(LocalStringUtils.formatEmptyValue(picturePath));
            qcSourceDao.save(entity);
            return outputEncapsulationObject(PromptMessageEnum.SUCCESS, "添加成功!", locale);
        }
        return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "添加失败!", locale);
    }

    /**
     * 删除检验数据
     */
    @Transactional(rollbackOn = Exception.class)
    @Override
    public String deleteQcSource(QcSourceQoDelete deleteQo) {
        Integer id = deleteQo.getId();
        Optional<QcSourceEntity> entityById = qcSourceDao.findById(id);
        if (entityById.isEmpty()) {
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "不存在该检验数据,请先添加检验数据!", locale);
        }
        qcSourceDao.deleteById(id);
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS, "删除成功!", locale);
    }

    /**
     * 查询检验数据
     */
    @Override
    public String queryQcSource(String batchNo, String machineNo, String materialNo, String mouldNo, String varietyNo, String craftItemNo) {
        List<CraftItemEntity> craftItemList = craftItemDao.findAll();
        if (craftItemList.isEmpty()) {
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "未添加工艺项目,请先添加工艺项目!", locale);
        }
        List<QcItemEntity> qcItemList = qcItemDao.findAll();
        if (qcItemList.isEmpty()) {
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "未添加检验项目,请先添加检验项目!", locale);
        }
        String finalBatchNo = LocalStringUtils.formatEmptyValue(batchNo).trim();
        String finalMachineNo = LocalStringUtils.formatEmptyValue(machineNo).trim();
        String finalMaterialNo = LocalStringUtils.formatEmptyValue(materialNo).trim();
        String finalMouldNo = LocalStringUtils.formatEmptyValue(mouldNo).trim();
        String finalVarietyNo = LocalStringUtils.formatEmptyValue(varietyNo).trim();
        List<Map<String, Object>> sourceList;
        if (TextUtils.isEmpty(craftItemNo)) {
            sourceList = qcSourceDao.queryQcSource(finalBatchNo, finalMachineNo, finalMaterialNo, finalMouldNo, finalVarietyNo);
        } else {
            sourceList = qcSourceDao.queryQcSource(finalBatchNo, finalMachineNo, finalMaterialNo, finalMouldNo, finalVarietyNo, craftItemNo.trim());
        }
        List<Map<String, Object>> resultList = generateResultList(sourceList);
        if (resultList.isEmpty()) {
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "暂时没有该检验数据的信息!", locale);
        }
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS, resultList, locale);
    }

    /**
     * 生成返回结果
     */
    private List<Map<String, Object>> generateResultList(List<Map<String, Object>> sourceList) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (sourceList == null || sourceList.isEmpty()) {
            return resultList;
        }
        for (Map<String, Object> source : sourceList) {
            String batchNo = (String) source.getOrDefault("batchNo", "");
            String machineNo = (String) source.getOrDefault("machineNo", "");
            String materialNo = (String) source.getOrDefault("materialNo", "");
            String mouldNo = (String) source.getOrDefault("mouldNo", "");
            String varietyNo = (String) source.getOrDefault("varietyNo", "");
            String craftItemNo = (String) source.getOrDefault("craftItemNo", "");
            String qcItemNo = (String) source.getOrDefault("qcItemNo", "");
            String qcValue = (String) source.getOrDefault("qcValue", "");
            if (TextUtils.isEmpty(qcItemNo) || TextUtils.isEmpty(qcValue)) {
                continue;
            }
            String formatValue = getFormatValue(varietyNo, craftItemNo, qcItemNo, qcValue);
            Map<String, Object> emptyRoom = findEmptyRoom(resultList, qcItemNo, batchNo, machineNo, materialNo, mouldNo, varietyNo, craftItemNo);
            if (emptyRoom == null) {
                Map<String, Object> newRoom = new HashMap<>();
                newRoom.put(EXCEL_HEAD_STYLE_ONE_NO.get(0), batchNo);
                newRoom.put(EXCEL_HEAD_STYLE_ONE_NO.get(1), machineNo);
                newRoom.put(EXCEL_HEAD_STYLE_ONE_NO.get(2), materialNo);
                newRoom.put(EXCEL_HEAD_STYLE_ONE_NO.get(3), mouldNo);
                newRoom.put(EXCEL_HEAD_STYLE_ONE_NO.get(4), varietyNo);
                newRoom.put(EXCEL_HEAD_STYLE_ONE_NO.get(5), craftItemNo);
                newRoom.put(qcItemNo, formatValue);
                resultList.add(newRoom);
            } else {
                emptyRoom.put(qcItemNo, formatValue);
            }
        }
        return resultList;
    }

    /**
     * 获取添加了 ##H 或 ##L 后缀的测量值(如果可能的话)
     */
    private String getFormatValue(String varietyNo, String craftItemNo, String qcItemNo, String qcValue) {
        Optional<QcSpecEntity> existsQcSpecOptional = qcSpecDao.findExistsQcSpec(varietyNo, craftItemNo, qcItemNo);
        if (existsQcSpecOptional.isEmpty()) {
            return qcValue;
        }
        QcSpecEntity existsQcSpec = existsQcSpecOptional.get();
        double valueMax = stringToDouble(existsQcSpec.getMax());
        double valueMin = stringToDouble(existsQcSpec.getMin());
        double value = stringToDouble(qcValue);
        if (valueMax > -99_000D && value > -99_000D && value >= valueMax) {
            return qcValue + "##H";
        }
        if (valueMin > -99_000D && value > -99_000D && value <= valueMin) {
            return qcValue + "##L";
        }
        return qcValue;
    }

    /**
     * 格式化字符串为Double
     */
    private Double stringToDouble(String stringValue) {
        try {
            return Double.parseDouble(stringValue);
        } catch (Exception e) {
            e.printStackTrace();
            return -100_000D;
        }
    }

    /**
     * 尝试找到一个qcItemNo有空位置的Map
     */
    private Map<String, Object> findEmptyRoom(List<Map<String, Object>> mapList, String qcItemNo, String batchNo, String machineNo, String materialNo, String mouldNo, String varietyNo, String craftItemNo) {
        if (mapList == null || mapList.isEmpty() || TextUtils.isEmpty(qcItemNo)) {
            return null;
        }
        for (Map<String, Object> room : mapList) {
            if (room.getOrDefault("batchNo", "").equals(batchNo) && room.getOrDefault("machineNo", "").equals(machineNo) && room.getOrDefault("materialNo", "").equals(materialNo) && room.getOrDefault("mouldNo", "").equals(mouldNo) && room.getOrDefault("varietyNo", "").equals(varietyNo) && room.getOrDefault("craftItemNo", "").equals(craftItemNo)) {
                if (!room.containsKey(qcItemNo)) {
                    return room;
                }
            }
        }
        return null;
    }

    /**
     * 导出Excel表格
     */
    @Override
    public String exportExcel(ExportSourceExcelQo exportSourceExcelQo) throws Exception {
        String host = exportSourceExcelQo.getHost();
        String finalBatchNo = LocalStringUtils.formatEmptyValue(exportSourceExcelQo.getBatchNo()).trim();
        String finalMachineNo = LocalStringUtils.formatEmptyValue(exportSourceExcelQo.getMachineNo()).trim();
        String finalMaterialNo = LocalStringUtils.formatEmptyValue(exportSourceExcelQo.getMaterialNo()).trim();
        String finalMouldNo = LocalStringUtils.formatEmptyValue(exportSourceExcelQo.getMouldNo()).trim();
        String finalVarietyNo = LocalStringUtils.formatEmptyValue(exportSourceExcelQo.getVarietyNo()).trim();
        String craftItemNo = exportSourceExcelQo.getCraftItemNo();
        List<CraftItemEntity> craftItemList = craftItemDao.findAll();
        if (craftItemList.isEmpty()) {
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "未添加工艺项目,请先添加工艺项目!", locale);
        }
        List<QcItemEntity> qcItemList = qcItemDao.findAll();
        if (qcItemList.isEmpty()) {
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "未添加检验项目,请先添加检验项目!", locale);
        }
        List<Map<String, Object>> sourceList;
        if (TextUtils.isEmpty(craftItemNo)) {
            sourceList = qcSourceDao.queryQcSource(finalBatchNo, finalMachineNo, finalMaterialNo, finalMouldNo, finalVarietyNo);
        } else {
            sourceList = qcSourceDao.queryQcSource(finalBatchNo, finalMachineNo, finalMaterialNo, finalMouldNo, finalVarietyNo, craftItemNo.trim());
        }
        List<Map<String, Object>> resultList = generateResultList(sourceList);
        String finalHost = host.endsWith("/") ? host : host + "/";
        List<List<String>> formattedResultList = formatResultList(finalHost, resultList, qcItemList);
        if (formattedResultList.isEmpty()) {
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "暂时没有该检验数据的信息!", locale);
        }
        String excelPath = doExportExcel(formattedResultList);
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS, finalHost + excelPath, locale);
    }

    /**
     * 格式化结果集数据
     */
    private List<List<String>> formatResultList(String host, List<Map<String, Object>> resultList, List<QcItemEntity> qcItemList) {
        List<List<String>> formatResultList = new ArrayList<>();
        if (resultList == null || resultList.isEmpty()) {
            return formatResultList;
        }
        List<String> headList = new ArrayList<>(EXCEL_HEAD_STYLE_ONE_NAME);
        for (QcItemEntity qcItemEntity : qcItemList) {
            headList.add(qcItemEntity.getQcItemName());
        }
        formatResultList.add(headList);
        for (Map<String, Object> dataMap : resultList) {
            List<String> dataList = new ArrayList<>();
            dataList.add((String) dataMap.getOrDefault(EXCEL_HEAD_STYLE_ONE_NO.get(0), ""));
            dataList.add((String) dataMap.getOrDefault(EXCEL_HEAD_STYLE_ONE_NO.get(1), ""));
            dataList.add((String) dataMap.getOrDefault(EXCEL_HEAD_STYLE_ONE_NO.get(2), ""));
            dataList.add((String) dataMap.getOrDefault(EXCEL_HEAD_STYLE_ONE_NO.get(3), ""));
            dataList.add((String) dataMap.getOrDefault(EXCEL_HEAD_STYLE_ONE_NO.get(4), ""));
            dataList.add((String) dataMap.getOrDefault(EXCEL_HEAD_STYLE_ONE_NO.get(5), ""));
            for (QcItemEntity entity : qcItemList) {
                String value = (String) dataMap.getOrDefault(entity.getQcItemNo(), "");
                if (Constant.QC_ITEM_TYPE_STRING.equals(entity.getQcItemType())) {
                    dataList.add(value);
                } else if (Constant.QC_ITEM_TYPE_PICTURE.equals(entity.getQcItemType())) {
                    if (value.startsWith("picture")) {
                        dataList.add(host + value);
                    } else {
                        dataList.add(value);
                    }
                } else {
                    dataList.add(value);
                }
            }
            formatResultList.add(dataList);
        }
        return formatResultList;
    }

    /**
     * 将格式化后的结果集数据导出为Excel文件
     */
    private String doExportExcel(List<List<String>> dataListList) throws Exception {
        //创建XSSFWorkbook对象(excel的文档对象)
        XSSFWorkbook workbook = new XSSFWorkbook();
        //建立新的sheet对象(excel的表单)
        XSSFSheet sheet = workbook.createSheet("检验数据表");
        for (int i = 0; i < dataListList.get(0).size(); i++) {
            if (i <= 5) {
                sheet.setColumnWidth(i, 20 * 256);
            } else {
                sheet.setColumnWidth(i, 14 * 256);
            }
        }
        XSSFCellStyle headCellStyle = workbook.createCellStyle();
        headCellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        headCellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        XSSFFont headFont = workbook.createFont();
        headFont.setColor(HSSFColor.BLACK.index);
        headCellStyle.setFont(headFont);
        headCellStyle.setFillForegroundColor(new XSSFColor(new Color(156, 195, 230)));//设置背景色
        headCellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);//填充模式

        XSSFCellStyle highCellStyle = workbook.createCellStyle();
        highCellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        highCellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        XSSFFont highFont = workbook.createFont();
        highFont.setColor(HSSFColor.RED.index);
        highCellStyle.setFont(highFont);

        XSSFCellStyle lowCellStyle = workbook.createCellStyle();
        lowCellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        lowCellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        XSSFFont lowFont = workbook.createFont();
        lowFont.setColor(HSSFColor.BLUE.index);
        lowCellStyle.setFont(lowFont);

        XSSFCellStyle normalCellStyle = workbook.createCellStyle();
        normalCellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        normalCellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        XSSFFont normalFont = workbook.createFont();
        normalFont.setColor(HSSFColor.BLACK.index);
        normalCellStyle.setFont(normalFont);

        //在sheet里创建第一行,参数为行索引(excel的行),可以是0~65535之间的任何一个
        XSSFRow titleRow = sheet.createRow(0);
        //创建单元格(excel的单元格,参数为列索引,可以是0~255之间的任何一个
        XSSFCell titleCell = titleRow.createCell(0);
        //设置单元格内容
        titleCell.setCellValue("检验数据导出表");
        titleCell.setCellStyle(normalCellStyle);
        //合并单元格CellRangeAddress构造参数依次表示起始行,截至行,起始列, 截至列
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, dataListList.get(0).size() - 1));
        int startRowNum = 1;
        for (int i = 0; i < dataListList.size(); i++) {
            List<String> dataList = dataListList.get(i);
            if (dataList != null && dataList.size() > 0) {
                XSSFRow row = sheet.createRow(i + startRowNum);
                for (int j = 0; j < dataList.size(); j++) {
                    XSSFCell cell = row.createCell(j);
                    String sourceValue = dataList.get(j);
                    if (i == 0) {
                        cell.setCellValue(sourceValue);
                        cell.setCellStyle(headCellStyle);
                    } else if (j <= 5) {
                        cell.setCellValue(sourceValue);
                        cell.setCellStyle(normalCellStyle);
                    } else if (sourceValue.contains("##H")) {
                        cell.setCellValue(LocalDoubleUtils.keepThreeDecimal(sourceValue.split("##")[0]));
                        cell.setCellStyle(highCellStyle);
                    } else if (sourceValue.contains("##L")) {
                        cell.setCellValue(LocalDoubleUtils.keepThreeDecimal(sourceValue.split("##")[0]));
                        cell.setCellStyle(lowCellStyle);
                    } else {
                        XSSFCellDataBean cellDataBean = new XSSFCellDataBean(sourceValue);
                        if (XSSFCellDataBean.VALUE_TYPE_STRING == cellDataBean.getValueType()) {
                            cell.setCellValue(cellDataBean.getStringValue());
                        } else if (XSSFCellDataBean.VALUE_TYPE_DOUBLE == cellDataBean.getValueType()) {
                            cell.setCellValue(LocalDoubleUtils.keepThreeDecimal(cellDataBean.getDoubleValue()));
                        }
                        cell.setCellStyle(normalCellStyle);
                    }
                }
            }
        }
        //输出Excel文件
        File dirFile = new File("/home/sxy/server/industrial_measurement/excel/");
//        File dirFile = new File("/Users/liuchengqian/Desktop/DaJiang/");
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        String excelFileName = System.currentTimeMillis() + ".xlsx";
        FileOutputStream output = new FileOutputStream(new File(dirFile, excelFileName));
        workbook.write(output);
        output.flush();
        return "excel/" + excelFileName;
    }


}