package com.sptg.gateway.service;

import com.alibaba.excel.metadata.BaseRowModel;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.exception.ImportExcelException;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.permissions.api.entity.ImportExcelError;
import com.sptg.permissions.api.feigns.ImportExcelErrorFeign;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.scheduling.annotation.Async;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;

/**
 * @author WFT
 * @date 2020/5/28
 * description:
 */
public interface ExcelService {

    String REGEX_EXCEL2003 = "^.+\\.(?i)(xls)$";
    String REGEX_EXCEL2007 = "^.+\\.(?i)(xlsx)$";

    /**
     *
     * @param fileName 文件名
     * @param inputStream java.io.InputStream
     * @return org.apache.poi.ss.usermodel.Workbook
     */
    default Workbook getWorkbook(String fileName, InputStream inputStream) throws IOException {
        if (fileName.matches(REGEX_EXCEL2007)) {
            return new XSSFWorkbook(inputStream);
        }
        if (fileName.matches(REGEX_EXCEL2003)) {
            return new HSSFWorkbook(inputStream);
        }
        throw new RuntimeException("文件类型错误,请重新选择");
    }

    /**
     * 获取标识
     * @return java.lang.String
     */
    String getFlag();

    /**
     * 获取表格模板名称
     * @return java.lang.String
     */
    String getExcelTemplateName();

    /**
     * 获取表格模板
     * @return com.alibaba.excel.metadata.BaseRowModel
     */
    BaseRowModel getExcelTemplate();

    /**
     * 读取数据
     * @param sheet org.apache.poi.ss.usermodel.Sheet
     */
    @Async
    default void read(Sheet sheet, ImportExcelErrorFeign feign){
        //  遍历记录
        for (int i = 1; i < sheet.getLastRowNum(); i++){
            Object data = null;
            try {
                //  读取行中的记录
                data = this.read(sheet.getRow(i));
                if (null == data){
                    continue;
                }
                //  保存记录
                ResultBean<?> result = this.save(data);
                //  判断是否保存失败
                if (null == result){
                    throw new ImportExcelException("保存失败,服务器异常",data);
                } else if (!result.getCode().equals(ResultEnum.SUCCESS.getCode())){
                    throw new ImportExcelException(result.getMsg(),data);
                }
            } catch (ImportExcelException e){
                if (!StringUtils.isEmpty(e.getData())) {
                    feign.add(new ImportExcelError(this.getFlag(), e.getMessage(), e.getData()));
                }
            } catch (RuntimeException e){
                e.printStackTrace();
                feign.add(new ImportExcelError(this.getFlag(),e.getMessage(), JsonUtils.objectToJson(data)));
            }
            //  判断下一行是否还有记录
            Row nextRow = sheet.getRow(i + 1);
            if (null == nextRow || null == this.getValue(nextRow.getCell(0))){
                break;
            }
        }
        System.out.println("表格导入结束 flag:" + this.getFlag());
    }

    /**
     * 读取数据
     * @param row org.apache.poi.ss.usermodel.Row
     * @return 返回值为Null时表示数据已存在
     */
    Object read(Row row) throws ImportExcelException;

    /**
     * 保存数据
     * @param data java.lang.Object
     * @return com.sptg.common.core.beans.ResultBean
     */
    ResultBean<?> save(Object data);

    /**
     * 获取单元格的值
     * @param cell org.apache.poi.ss.usermodel.Cell
     * @return java.lang.String
     */
    default String getValue(Cell cell){
        if (null == cell){
            return null;
        }
        switch (cell.getCellTypeEnum()){
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)){
                    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cell.getDateCellValue());
                }
                return new BigDecimal(cell.getNumericCellValue()).toString().trim();
            case STRING:
                return StringUtils.trimToEmpty(cell.getStringCellValue()).trim();
            case FORMULA:
                return StringUtils.trimToEmpty(cell.getCellFormula()).trim();
            case BLANK:
                return null;
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue()).trim();
            case ERROR:
                return null;
            default:
                return cell.toString().trim();
        }
    }
}
