package com.boman.file.service;

import com.alibaba.fastjson.JSONObject;
import com.boman.common.core.utils.obj.ObjectUtils;
import com.boman.common.core.utils.poi.ExcelUtil;
import com.boman.domain.dto.AjaxResult;
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.constant.MaskConstant;
import com.boman.domain.dto.ExportExcelDto;
import com.boman.domain.dto.FormDataDto;
import com.boman.domain.dto.ImportExcelDto;
import com.boman.file.utils.FileUploadUtils;
import com.boman.web.core.api.RemoteObjService;
import org.apache.commons.lang3.BooleanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

import static com.boman.common.core.utils.obj.ObjectUtils.map;

/**
 * 本地文件存储
 * 
 * @author ruoyi
 */
@Primary
@Service
@RefreshScope
public class LocalSysFileServiceImpl implements ISysFileService
{

    private static final Logger LOGGER = LoggerFactory.getLogger(LocalSysFileServiceImpl.class);

    @Resource
    private RemoteObjService remoteObjService;
    @Resource
    private RedisService redisService;

    /**
     * 资源映射路径 前缀
     */
    @Value("${file.prefix}")
    public String localFilePrefix;

    /**
     * 域名或本机访问地址
     */
    @Value("${file.domain}")
    public String domain;
    
    /**
     * 上传文件存储在本地的根路径
     */
    @Value("${file.path}")
    private String localFilePath;

    /**
     * 本地文件上传接口
     * 
     * @param file 上传的文件
     * @return 访问地址
     * @throws Exception
     */
    @Override
    public String uploadFile(MultipartFile file) throws Exception
    {
        String name = FileUploadUtils.upload(localFilePath, file);
        String url = domain + localFilePrefix + name;
        LOGGER.info("上传的路径为: {}", url);
        return url;
    }

    /**
     * 功能描述: 上传base64
     *
     * @param base64 base64
     * @return java.lang.String
     */
    @Override
    public String uploadFileBase64(String base64) throws IOException {
        MultipartFile multipartFile = FileUploadUtils.base64ToMultipart(base64);
        String name = FileUploadUtils.upload(localFilePath, multipartFile);
        String path = domain + localFilePrefix + name;
        LOGGER.info("上传的路径为: {}", path);
        return path;
    }

    /**
     * 功能描述: 通用的导入接口
     *
     * @param multipartFile multipartFile
     * @param tableName     tableName
     * @return java.util.List<com.alibaba.fastjson.JSONObject>
     */
    @Override
    public AjaxResult importExcelCommon(MultipartFile multipartFile, String tableName) throws Exception {
        Objects.requireNonNull(multipartFile, "multipartFile is empty");
        ObjectUtils.requireNonNull(tableName, "tableName is empty");

        GenTable genTable = redisService.getCacheObject(RedisKey.TABLE_INFO + tableName);
        List<GenTableColumn> columns = genTable.getColumns();

        ExcelUtil<JSONObject> util = new ExcelUtil<>(JSONObject.class);
        List<JSONObject> list = util.importCommonExcel("", multipartFile.getInputStream(), columns);

        ImportExcelDto dto = new ImportExcelDto();
        dto.setDataList(list);
        dto.setTableName(tableName);

        return remoteObjService.importCommonData(dto);
    }

    /**
     * 功能描述: 通用的导出接口
     *
     * @param response response
     * @param dto      tableName
     *                 empty(true=>只带表头的excel，不含数据, false=>带数据的excel)
     *                 condition 查询条件
     * @return com.boman.domain.dto.AjaxResult
     */
    @Override
    public AjaxResult exportExcelCommon(HttpServletResponse response, ExportExcelDto dto) {
        String tableName = dto.getTableName();
        Boolean empty = dto.getEmpty();
        ObjectUtils.requireNonNull(tableName, "exportExcelCommon tableName is empty");
        ObjectUtils.requireNonNull(empty, "exportExcelCommon empty is empty");

        GenTable genTable = redisService.getCacheObject(RedisKey.TABLE_INFO + tableName);
        List<GenTableColumn> columns = genTable.getColumns();

        ExcelUtil<JSONObject> util = new ExcelUtil<>(JSONObject.class);
        List<Map<String, Object>> list = null;
        if (BooleanUtils.isTrue(empty)) {
            list = new ArrayList<>(0);
        } else {
            FormDataDto condition = new FormDataDto();
            condition.setTable(tableName);
            condition.setFixedData(new JSONObject(dto.getCondition()));
            AjaxResult ajaxResult = remoteObjService.getByMap(condition);
            if (AjaxResult.checkSuccess(ajaxResult)) {
                list = ((List<Map<String, Object>>) ajaxResult.get(AjaxResult.DATA_TAG));
                columns = ExcelUtil.filterData(columns, 4, MaskConstant.LIST_VISIBLE::equals);
                handleNullColumnValue(list, map(columns, GenTableColumn::getColumnName));
            }
        }

        try {
            util.exportExcelCommon(response, list, "sheet1", columns, empty);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**f
     * 功能描述: 通用的导入接口
     *
     * @param dto@return java.util.List<com.alibaba.fastjson.JSONObject>
     */
    @Override
    public List<JSONObject> importExcelCommon(ImportExcelDto dto) throws Exception {
        return null;
    }

    public void handleNullColumnValue(List<Map<String, Object>> result, List<String> showData) {
        for (Map<String, Object> map : result) {
            Set<String> resultKeySet = map.keySet();
            for (String columnName : showData) {
                if (!resultKeySet.contains(columnName)) {
                    map.put(columnName, "");
                }
            }
        }
    }
}
