package com.boman.report.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.boman.common.core.utils.CollectUtils;
import com.boman.common.core.utils.StringUtils;
import com.boman.common.core.utils.obj.ObjectUtils;
import com.boman.common.core.utils.poi.ExcelUtil;
import com.boman.common.redis.RedisKey;
import com.boman.common.redis.service.RedisService;
import com.boman.domain.GenTable;
import com.boman.domain.GenTableColumn;
import com.boman.domain.dto.AjaxResult;
import com.boman.domain.dto.ImportExcelDto;
import com.boman.domain.dto.ImportFileDto;
import com.boman.domain.entity.StatisticReportPersonnel;
import com.boman.report.mapper.ImportMapper;
import com.boman.report.service.IImportServcie;
import com.boman.report.service.StatisticReportPersonnelService;
import com.boman.web.core.api.RemoteObjService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.util.*;

/**
 * 导入服务类
 */
@Service
public class ImportServiceImpl implements IImportServcie {

    private static final Logger logger = LoggerFactory.getLogger(ImportServiceImpl.class);

    private static final String CREATE_BY = "create_by";
    private static final String CREATE_TIME = "create_time";
    private static final String UPDATE_BY = "update_by";
    private static final String UPDATE_TIME = "update_time";

    @Autowired
    private ImportMapper importMapper;
    @Autowired
    private RedisService redisService;
    @Autowired
    private RemoteObjService remoteObjService;
    @Autowired
    private StatisticReportPersonnelService personnelService;

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public AjaxResult importData(ImportFileDto fileDto, Long personnelId, String tableName) throws Exception {
        Objects.requireNonNull(fileDto, "未上传文件！");
        ObjectUtils.requireNonNull(tableName, "表名为空！");
        GenTable genTable = redisService.getCacheObject(RedisKey.TABLE_INFO + tableName);
        Map<String, GenTableColumn> columnMap = this.genImportColumn(genTable.getColumns());
        List<GenTableColumn> columns = genColumData(tableName, columnMap);
        this.genBaseData(columns,  columnMap);
        ExcelUtil<JSONObject> util = new ExcelUtil<>(JSONObject.class);

        String realPath = getFileRealPath(fileDto);
        File file = new File(realPath);
        List<JSONObject> list = util.importCommonExcel("", new FileInputStream(file), columns);
        ImportExcelDto dto = new ImportExcelDto();
        dto.setDataList(list);
        dto.setTableName(tableName);

        try {
            remoteObjService.importCommonData(dto);
        }catch (Exception e) {
            e.printStackTrace();
        }

        // 上传成功后需要修改上报人的状态
        StatisticReportPersonnel personnel = new StatisticReportPersonnel();
        personnel.setId(personnelId);
        personnel.setStatus("2");

        JSONObject json = (JSONObject) JSONObject.toJSON(fileDto);

        personnel.setUploadFile(JSON.toJSONString(CollectUtils.newArrayList(json)));
        personnelService.updateStatus(personnel);
        return AjaxResult.success();
    }

    /**
     * 将列组装成map，方便判断，无需多次循环
     *
     * @param allColumns
     * @return
     */
    private Map<String, GenTableColumn> genImportColumn(List<GenTableColumn> allColumns) {
        Map<String, GenTableColumn> columnMap = new HashMap<>();
        for (GenTableColumn column : allColumns) {
            String columnName = column.getColumnName();
            columnMap.put(columnName, column);
        }
        return columnMap;
    }

    /**
     * 根据报表设计中的表格字段获取gentable中的数据，用于导出
     *
     * 数据格式："rows":{
     * 	"0":{
     * 		"cells":{
         * 		"0":{
         * 			"text":"#{urge_read_message.message_title}",
         * 			"style":2
         *                },
         * 		"1":{
         * 			"text":"#{urge_read_message.send_user_id}",
         * 			"style":2
         *        },
         * 		"2":{
         * 			"text":"#{urge_read_message.receive_user_name}",
         * 			"style":2
         *        },
         * 		"3":{
         * 			"style":2,
         * 			"text":"#{urge_read_message.is_del}"
         *        }* 	},
         * 	"len":100
     * },
     * @param tableName
     * @param columnMap 列map集合
     * @return
     */
    private List<GenTableColumn> genColumData(String tableName, Map<String, GenTableColumn> columnMap) {
        List<GenTableColumn> columns = new ArrayList<>();
        // 根据名获取报表设计相关数据
        JSONObject designObject = importMapper.getReportDesignData(tableName);
        if(designObject == null) {
            AjaxResult.error("数据表没有设计报表模板！请先设计报表模板！");
        }
        String jsonStr = designObject.getString("jsonStr");
        if(StringUtils.isEmpty(jsonStr)) {
            AjaxResult.error("报表模板没有相关设计数据，请确认是否设计好报表模板！");
        }
        JSONObject rowDatas = JSONObject.parseObject(jsonStr).getJSONObject("rows");
        int maxKey = rowDatas.size() - 1;
        Iterator<String> rowIterator = rowDatas.keySet().iterator();
        int count  = 0;
        while (rowIterator.hasNext()) {
            count ++;
            String key = rowIterator.next();
            if(count == maxKey) {
                JSONObject cells = JSONObject.parseObject(rowDatas.getString(key));
                Iterator<String> cellIterator = cells.keySet().iterator();
                while (cellIterator.hasNext()) {
                    String cellKey = cellIterator.next();
                    JSONObject feildJson = cells.getJSONObject(cellKey);
                    Iterator<String> feildIterator = feildJson.keySet().iterator();
                    while (feildIterator.hasNext()) {
                        String feildName = "";
                        String textStr = feildJson.getString(feildIterator.next());
                        if(StringUtils.isNotEmpty(textStr)) {
                            JSONObject textJson = JSONObject.parseObject(textStr);
                            String text = textJson.getString("text");
                            // 获取数据
                            if(StringUtils.isNotEmpty(text)) {
                                String realText = text.replace("#{", "").replace("}", "");
                                feildName = realText.substring(tableName.length() + 1, realText.length());
                                if(columnMap.containsKey(feildName)) {
                                    columns.add(columnMap.get(feildName));
                                }
                            }
                        }
                    }
                }
                break;
            }
        }
        return columns;
    }

    /**
     * 基础字段填充
     *
     * @param columns
     * @param columnMap
     */
    private void genBaseData(List<GenTableColumn> columns, Map<String, GenTableColumn> columnMap) {
        columns.add(columnMap.get(CREATE_BY));
        columns.add(columnMap.get(CREATE_TIME));
        columns.add(columnMap.get(UPDATE_BY));
        columns.add(columnMap.get(UPDATE_TIME));
    }

    private String getFileRealPath(ImportFileDto dto) {
        return dto.getAbsolutePath();
    }
}
