package pwc.taxtech.atms.service.impl;

import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.nutz.lang.Files;
import org.nutz.lang.Lang;
import org.nutz.lang.Streams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import pwc.taxtech.atms.common.ApplicationException;
import pwc.taxtech.atms.common.CommonConstants;
import pwc.taxtech.atms.common.CommonUtils;
import pwc.taxtech.atms.dto.OperationResultDto;
import pwc.taxtech.atms.thirdparty.ExcelLogs;
import pwc.taxtech.atms.thirdparty.ExcelUtil;

@Service
public class FileService {

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

    public OperationResultDto<Object> saveFile(InputStream inputStream, String filePath) {
        logger.debug("保存输入流到指定的路径, filePath:{}", filePath);
        OperationResultDto<Object> operationResultDto = new OperationResultDto<>();
        try {
            Files.write(filePath, inputStream);
            logger.debug("保存成功");
            operationResultDto.setResult(true);
        } catch (Exception e) {
            logger.error("Catch error", e);
            Map<String, String> error = new HashMap<>();
            error.put(CommonUtils.getUUID(), e.getMessage());
            operationResultDto.setResultMsg(CommonConstants.SAVE_FILE_ERROR);
            operationResultDto.setResult(false);
            operationResultDto.setErrors(error);
        }
        Assert.notNull(operationResultDto.getResult(), "Null result");
        return operationResultDto;
    }

    /** 读取Excel输入流, 最后关闭该输入流 */
    @SuppressWarnings("rawtypes")
    public Collection<Map> readExcelAndClose(InputStream inputStream) {
        logger.debug("读取Excel输入流");
        ExcelLogs logs = new ExcelLogs();
        Workbook workBook = null;
        try {
            
                workBook = WorkbookFactory.create(inputStream);
            Collection<Map> result = ExcelUtil.importExcel(Map.class, workBook, null, "yyyy/MM/dd HH:mm:ss", logs, 0);
            if (logs.getHasError() != null && logs.getHasError()) {
                throw new ApplicationException("Cannot read excel file");
            }
            logger.debug("读取Excel输入流成功, result size:{}", result.size());
            return result;
        } catch (Exception e) {
            logger.error("load excel file error", e);
            throw Lang.wrapThrow(e);
        } finally {
            logger.debug("关闭Excel输入流");
            Streams.safeClose(inputStream);
            if(workBook!=null) {
                try {
                    workBook.close();
                }
                catch (Exception e) {
                    logger.error("Error closing workbook", e);
                }
                finally {
                    workBook = null;
                }
            }
        }
    }
    
    /** 读取Excel输入流, 最后关闭该输入流 */
    @SuppressWarnings("rawtypes")
    public Map<String, Collection<Map>> readExcelAndClose(InputStream inputStream, String ...sheetNames) {
        
        logger.debug("读取Excel输入流");
        ExcelLogs logs = new ExcelLogs();
        Workbook workBook = null;
        try {
            workBook = WorkbookFactory.create(inputStream);
            Map<String, Collection<Map>> sheetMap = new HashMap<>();
            for(String sheetName: sheetNames) {
                Collection<Map> result = ExcelUtil.importExcel(Map.class, workBook, sheetName, "yyyy/MM/dd HH:mm:ss", logs, 0);
                if(result!=null) {
                    sheetMap.put(sheetName, result);
                }
            }
            if (logs.getHasError() != null && logs.getHasError()) {
                throw new ApplicationException("Cannot read excel file");
            }
            logger.debug("读取Excel输入流成功, sheets number:{}", sheetMap.size());
            return sheetMap;
        } 
        catch (Exception e) {
            logger.error("load excel file error", e);
            throw Lang.wrapThrow(e);
        }
        finally {
            logger.debug("关闭Excel输入流");
            Streams.safeClose(inputStream);
            if(workBook!=null) {
                try {
                    workBook.close();
                }
                catch (Exception e) {
                    logger.error("Error closing workbook", e);
                }
                finally {
                    workBook = null;
                }
            }
        }
    }
    
    /** 读取Excel输入流, 最后关闭该输入流 */
    public Map<String, Integer> readExcelHeaderAndClose(InputStream inputStream) {
        
        logger.debug("读取Excel输入流");
        ExcelLogs logs = new ExcelLogs();
        Workbook workBook = null;
        try {
            workBook = WorkbookFactory.create(inputStream);
            Map<String, Integer> titleMap = ExcelUtil.importExcelHeader(workBook, null);
            if (logs.getHasError() != null && logs.getHasError()) {
                throw new ApplicationException("Cannot read excel file");
            }
            logger.debug("读取Excel输入流成功, header size:{}", titleMap.size());
            return titleMap;
        } catch (Exception e) {
            logger.error("Load excel file error",e);
            throw Lang.wrapThrow(e);
        } finally {
            logger.debug("关闭Excel输入流");
            Streams.safeClose(inputStream);
            if(workBook!=null) {
                try {
                    workBook.close();
                }
                catch (Exception e) {
                    logger.error("Error closing workbook", e);
                }
                finally {
                    workBook = null;
                }
            }
        }
    }
    
    /** 读取Excel输入流, 最后关闭该输入流 */
    public Map<String, Map<String, Integer>> readExcelHeaderAndClose(InputStream inputStream, String ...sheetNames) {
        
        logger.debug("读取Excel输入流");
        ExcelLogs logs = new ExcelLogs();
        Workbook workBook = null;
        try {
            workBook = WorkbookFactory.create(inputStream);
            Map<String, Map<String, Integer>> sheetTitleMap = new HashMap<>();
            for(String sheetName: sheetNames) {
                Map<String, Integer> titleMap = ExcelUtil.importExcelHeader(workBook, sheetName);
                if(titleMap!=null) {
                    sheetTitleMap.put(sheetName, titleMap);
                }
            }
            if (logs.getHasError() != null && logs.getHasError()) {
                throw new ApplicationException("Cannot read excel file");
            }
            logger.debug("读取Excel输入流成功, sheet size:{}", sheetTitleMap.size());
            return sheetTitleMap;
        } catch (Exception e) {
            logger.error("Load excel file error",e);
            throw Lang.wrapThrow(e);
        } finally {
            logger.debug("关闭Excel输入流");
            Streams.safeClose(inputStream);
            if(workBook!=null) {
                try {
                    workBook.close();
                }
                catch (Exception e) {
                    logger.error("Error closing workbook", e);
                }
                finally {
                    workBook = null;
                }
            }
        }
    }

}