package com.ruoyi.project.common.controller;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.ruoyi.common.exception.ServiceErrorException;
import com.ruoyi.common.importExcel.excel.BasicUploadParam;
import com.ruoyi.common.importExcel.excel.EasyPoiHelper;
import com.ruoyi.common.importExcel.excel.TableTypeEnum;
import com.ruoyi.common.importExcel.excel.download.BasicDownloadParams;
import com.ruoyi.common.importExcel.excel.helper.BasicExcelHelper;
import com.ruoyi.common.importExcel.excel.helper.BasicTableInfoHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.*;
import com.ruoyi.common.importExcel.excel.validation.BasicDataValidation;
import com.ruoyi.common.importExcel.utils.FileUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.business.service.*;
import com.ruoyi.project.common.domain.CheckVO;
import com.ruoyi.project.common.service.ICommonService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.BiFunction;


import static com.ruoyi.common.importExcel.excel.TableTypeEnum.*;
import static com.ruoyi.common.importExcel.utils.ExcelUtils.*;
import static java.util.stream.Collectors.toList;

/**
 * 前端控制器
 *
 * @author CAC
 * @date 2021-01-15 12:00:00
 */
@Api(tags = "Excel", value = "excel相关接口")
@RestController
@RequestMapping(value = "/excel", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Validated
public class ExcelRestController {

    @Resource
    private FileUtils fileUtils;
    @Resource
    private ICommonService commonService;
    @Resource
    private ITpParaLibraryService tpParaLibraryService;
    @Resource
    private ITpAreaElevatorModelParaService tpAreaElevatorModelParaService;
    @Resource
    private ITcAccountService tcAccountService;
    @Resource
    private ITcLeadService tcLeadService;
    @Resource
    private ITpElevatorModelService tpElevatorModelService;


    @ApiOperation(value = "下载模板信息")
    @PostMapping("/downloadTemplate")
    public void downloadTemplate(HttpServletRequest request, HttpServletResponse response, @RequestBody BasicDownloadParams params) {
        String tableName = params.getTableName();
        TableTypeEnum tableType;

        Locale locale = LocaleContextHolder.getLocale();
        try {
            //tableType = getEnum(valueOfName(tableName));
            //tableType = getEnum(valueOfName(tableName, locale));
            tableType = getEnum(params.getTableType());
        } catch (Exception e) {
            e.printStackTrace();
            //下载失败，模板不存在
            throw new ServiceErrorException(MessageUtils.message("excel.message.filenotexist"));
        }

        // 1. 每个List对应一个sheet中的数据
        List<List<? extends BasicExcelHelper>> data = Lists.newArrayList();
        // 2. 基本导入信息
        List<BasicTableInfoHelper> tableInfoList = Lists.newArrayList();
        BasicTableInfoHelper tableInfo = new BasicTableInfoHelper();
        // 3. 数据验证等相关表单限制
        BasicDataValidation dataValidation = null;

         switch (tableType) {
             case ACCOUNT_EXCEL:
                break;
             case ParaLibrary_Excel:
                 break;
             case Elevator_Model_Excel:
                 break;
             case LEAD_IMPORT_EXCEL:
                 break;
             case PRICE_FORM_EXCEL:
                 break;
             default:
                 //不支持的导入类型
                throw new ServiceErrorException(MessageUtils.message("excel.message.unsupport"));
        }
        // 设置基本导入信息
        if (Objects.nonNull(tableInfo)){
            tableInfo.setTableName(tableType.getName());
            tableInfoList.add(tableInfo);
            data.add(0, tableInfoList);
        }
        //fileUtils.downloadTemplate(request, response, params.getFileName(), data);
        fileUtils.downloadTemplate(request, response, getFileNames(tableType, locale), data);
        //fileUtils.downloadTemplate(request, response, fileUtils.getFileNames(tableType, locale), data);
    }

    /**
     * 读取excel获取基本导入信息和导入数据并返回
     *
     * @param file
     * @return
     */
    @ApiOperation(value = "校验excel信息")
    @PostMapping("/check")
    public AjaxResult check(CheckVO checkVO,MultipartFile file) {
        XSSFWorkbook workbook = createWorkbook(file);

        // 1.获取基本导入信息(用于区分不同的导入，如有额外信息需要在各自处理逻辑中重新读取)
        XSSFSheet sheet = workbook.getSheetAt(0);
        BasicTableInfoHelper tableInfo = getTableInfo(sheet, BasicTableInfoHelper.class);

        // 2.获取所有导入数据表
        List<XSSFSheet> sheets = Lists.newArrayList();
        for (int i = 1; i < workbook.getNumberOfSheets(); i++) {
            sheets.add(workbook.getSheetAt(i));
        }

        UploadResult<? extends BasicExcelHelper> result = null;
        switch (getEnum(valueOfName(tableInfo.getTableName()))) {
            case ACCOUNT_EXCEL:
                tableInfo = getTableInfo(sheet, BasicTableInfoHelper.class);
                tableInfo.setCheckVO(checkVO);
                result = checkSheets(tcAccountService::checkAccountInfo, tableInfo, sheets, AccountInfoHelper.class);
                break;
            case ParaLibrary_Excel:
                tableInfo = getTableInfo(sheet, BasicTableInfoHelper.class);
                List<ParaLibraryExcel> list = EasyPoiHelper.importExcel(file, 0, 2, ParaLibraryExcel.class);
                result = checkSheetsByList(tpParaLibraryService::checkParaLibrary, tableInfo, list, ParaLibraryExcel.class);
                break;
            case Elevator_Model_Excel:
                tableInfo = getTableInfo(sheet, BasicTableInfoHelper.class);
                tableInfo.setCheckVO(checkVO);
                result = checkSheets(tpAreaElevatorModelParaService::checkElevatorParaInfo, tableInfo, sheets, ElevatorParaInfoHelper.class);
                break;
            case LEAD_IMPORT_EXCEL:
                tableInfo = getTableInfo(sheet, BasicTableInfoHelper.class);
                tableInfo.setCheckVO(checkVO);
                result = checkSheets(tcLeadService::checkLeadImport, tableInfo, sheets, LeadInfoHelper.class);
                break;
            case PRICE_FORM_EXCEL:
                tableInfo = getTableInfo(sheet, BasicTableInfoHelper.class);
                tableInfo.setCheckVO(checkVO);
                result = checkSheets(tpElevatorModelService::checkPriceFormImport, tableInfo, sheets, PriceFromInfoHelper.class);
                break;
                
            default:
                //不支持的导入类型
                throw new ServiceErrorException(MessageUtils.message("excel.message.unsupport"));
        }
        result.setData(tableInfo);
        return AjaxResult.success(result);
    }


    @ApiOperation(value = "批量保存excel信息")
    @PostMapping("/saveBatch")
    public AjaxResult saveBatch(@RequestBody BasicUploadParam<HashMap> param) {
        HashMap tableInfo = param.getTableInfo();
        if (Objects.isNull(tableInfo)) {
            //未获取到导入信息，请使用正确的模板
            throw new ServiceErrorException(MessageUtils.message("excel.message.rightFile"));
        }

        List<HashMap> dataList = param.getDataList();
        if (CollectionUtils.isEmpty(dataList)) {
            //throw new ServiceErrorException("导入信息不能为空");
            throw new ServiceErrorException(MessageUtils.message("excel.message.notEmpty"));
        }

        String tableName = (String) tableInfo.get("tableName");

        List<String> errMsgs = new ArrayList<>();
        TableTypeEnum tableType = getEnum(valueOfName(tableName));
        switch (tableType) {
            case ACCOUNT_EXCEL:
                errMsgs = tcAccountService.insertTcAccountExcel(new BasicTableInfoHelper(), transform(dataList, AccountInfoHelper.class));
                break;
            case ParaLibrary_Excel:
                errMsgs = tpParaLibraryService.insertTpParaLibraryExcel(transform(dataList, ParaLibraryExcel.class));
                break;
            case Elevator_Model_Excel:
                errMsgs = tpAreaElevatorModelParaService.insertElevatorModelParaExcel(new BasicTableInfoHelper(), transform(dataList, ElevatorParaInfoHelper.class));
                break;
            case LEAD_IMPORT_EXCEL:
                errMsgs = tcLeadService.insertLeadImportExcel(new BasicTableInfoHelper(), transform(dataList, LeadInfoHelper.class));
                break;
            default:
                //不支持的导入类型
                throw new ServiceErrorException(MessageUtils.message("excel.message.unsupport"));
        }
        Map<String,Object> result = new HashMap<>();
        if(ObjectUtils.isEmpty(errMsgs)){
            result.put("successList",dataList);
            result.put("errorList",new ArrayList<>());
            result.put("message",new ArrayList<>());
        }else {
            result.put("successList",new ArrayList<>());
            result.put("errorList",dataList);
            result.put("message",errMsgs);
        }
        return AjaxResult.success(result);
    }

    /**
     * 对多个表单校验应用校验方法(为了获取错误数据的位置，所以每个sheet单独校验)
     *
     * @param check
     * @param tableInfo
     * @param sheets
     * @param clazz
     * @param <T>
     * @param <U>
     * @return
     */
    private <T, U> UploadResult<U> checkSheets(BiFunction<T, List<U>, UploadResult<U>> check, T tableInfo, List<XSSFSheet> sheets, Class<U> clazz) {
        UploadResult<U> result = null;
        for (XSSFSheet sheet : sheets) {
            UploadResult<U> current = check.apply(tableInfo, readData(sheet, clazz))
                    .sheet(sheet.getSheetName());
            if (Objects.isNull(result)) {
                result = current;
            } else {
                result.join(current);
            }
        }
        return result;
    }

    private <T, U> UploadResult<U> checkSheetsByList(BiFunction<T, List<U>, UploadResult<U>> check, T tableInfo, List<U> list, Class<U> clazz) {
        UploadResult<U> result = null;
        result = check.apply(tableInfo, list);
        return result;
    }

    /**
     * 将hashmap集合转换成对应对象的集合
     *
     * @param data
     * @param clazz
     * @param <T>
     * @return
     */
    private <T> List<T> transform(List<HashMap> data, Class<? extends T> clazz) {
        return data.stream()
                .map(item -> JSON.parseObject(JSON.toJSONString(item), clazz))
                .filter(Objects::nonNull).collect(toList());
    }

    /**
     * 获取基本导入信息并返回相应对象
     *
     * @param sheet
     * @param clazz
     * @param <T>
     * @return
     */
    private <T> T getTableInfo(XSSFSheet sheet, Class<T> clazz) {
        List<T> tableInfoHelperList = readData(sheet, clazz);
        if (CollectionUtils.isEmpty(tableInfoHelperList)) {
            throw new ServiceErrorException(MessageUtils.message("excel.message.rightMB"));
            //throw new ServiceErrorException("无法获取模板基本信息，请使用正确的模板");
        }
        T tableInfo = tableInfoHelperList.get(0);
        return tableInfo;
    }
}
