
package com.lideeyunji.core.framework.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.lideeyunji.core.framework.config.btncommand.param.ButtonParamImport;
import com.lideeyunji.core.framework.entity.ExcelFileDataEntity;
import com.lideeyunji.core.framework.entity.ExcelFileEntity;
import com.lideeyunji.core.framework.params.UpdateFileDataParam;
import com.lideeyunji.core.framework.params.model.ExcelImportResultModel;
import com.lideeyunji.core.framework.params.vo.PageVo;
import com.lideeyunji.core.framework.service.IExcelFileDataService;
import com.lideeyunji.core.framework.service.IExcelFileService;
import com.lideeyunji.core.framework.service.IExcelService;
import com.lideeyunji.core.framework.service.IFormService;
import com.lideeyunji.core.framework.utils.Func;
import com.lideeyunji.core.framework.utils.FuncWeb;
import com.lideeyunji.tool.framework.common.constant.lideeYunJiBaseConstant;
import com.lideeyunji.tool.framework.constants.FrameErrorCodeConstants;
import com.lideeyunji.tool.framework.excel.lideeYunJiExcelUtils;
import com.lideeyunji.tool.framework.excel.model.ExcelTitleModel;
import com.lideeyunji.tool.framework.excel.model.MoreSheetConfig;
import com.lideeyunji.tool.framework.exception.lideeYunJiException;
import com.lideeyunji.tool.framework.yunji.adapter.IlideeYunjiAdapter;
import com.lideeyunji.tool.framework.yunji.component.properties.lideeYunjiProperties;
import com.lideeyunji.tool.framework.yunji.component.redis.lideeYunjiRedisUtils;
import com.lideeyunji.tool.framework.yunji.enums.YNEnum;
import com.lideeyunji.tool.framework.yunji.model.global.BaseWebResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.map.LinkedMap;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Tag(name = "低代码框架-框架接口-Excel相关")
@RestController
@AllArgsConstructor
@RequestMapping(lideeYunJiBaseConstant.REQUEST_URL_START + "/excel")
public class ExcelController extends BaseController {

    private final IFormService formService;

    private final IExcelFileDataService excelDataService;

    private final IExcelFileService excelFileService;

    private final IExcelService excelService;

    private final lideeYunjiRedisUtils lideeYunjiRedisUtils;

    private final IlideeYunjiAdapter lideeYunJiAdapter;

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @ApiOperationSupport(order = 1)
    @Operation(tags = "Excel模块",summary = "导出Excel模板")
    @GetMapping({"/exportExcelTemplate/{dbformId}"})
    public void exportExcelTemplate(@PathVariable("dbformId") Long dbformId, HttpServletResponse rsp) {
        MoreSheetConfig sheetConfig = super.exportExcelTemplate(dbformId);
        //导出
        lideeYunJiExcelUtils.exportExcel(rsp, sheetConfig.getSheetName(), sheetConfig.getHeadMap(), sheetConfig.getDataList());
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:export:'+#dbformId)")
    @ApiOperationSupport(order = 2)
    @Operation(tags = "Excel模块",summary = "导出Excel数据")
    @PostMapping({"/exportExcel/{dbformId}"})
    public void exportExcelData(@PathVariable("dbformId") Long dbformId, HttpServletRequest req, HttpServletResponse rsp) {
        Map<String, Object> params = FuncWeb.getParameterBodyMap(req);
        List<MoreSheetConfig> sheetList = super.exportExcelData(dbformId, params);
        String sheetName="数据导出";
        if(Func.isNotEmpty(sheetList)){
            sheetName=sheetList.get(0).getSheetName();
        }
        //导出
        lideeYunJiExcelUtils.exportExcel(rsp, sheetName, sheetList);
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @ApiOperationSupport(order = 3)
    @Operation(tags = "Excel模块",summary = "导入Excel数据到模板（预览）")
    @PostMapping({"/viewExcel/{dbformId}"})
    public BaseWebResult viewExcelData(@PathVariable("dbformId") Long dbformId, @RequestParam MultipartFile file) {
        try {
            String fileName = file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();
            //获取所有key
            Map<String, String> fieldNameAndCodeMap = formService.getFieldNameAndCode(dbformId);
            List<Map<String, Object>> dataMapList = lideeYunJiExcelUtils.importExcel(inputStream, 1, fieldNameAndCodeMap);
            if (Func.isEmpty(dataMapList)) {
                return BaseWebResult.error(FrameErrorCodeConstants.FRAME_IMPORT_EXCEL);
            }
            //封装参数
            ButtonParamImport buttonParam = new ButtonParamImport();
            buttonParam.setDbFormId(dbformId);
            buttonParam.setDataMapList(dataMapList);
            buttonParam.setFileName(fileName);//文件名称
            buttonParam.setServiceType("IMPORT_TEMPLATE");//业务类型

            ExcelImportResultModel resultModel = super.importExcelData(buttonParam);
            return BaseWebResult.success(resultModel);
        } catch (Exception e) {
            throw new lideeYunJiException("导入失败");
        }
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @ApiOperationSupport(order = 4)
    @Operation(tags = "Excel模块",summary = "查询导入进度")
    @GetMapping({"/viewProgress/{dbformId}"})
    public BaseWebResult viewProgress(@PathVariable("dbformId") Long dbformId, String batchCode) {
        //因为走事务控制，只需要查是否存在即可
        ExcelFileEntity excelFileEntity = excelFileService.getById(Func.toLong(batchCode));
        return BaseWebResult.success(Func.isNotEmpty(excelFileEntity));
    }


    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @ApiOperationSupport(order = 4)
    @Operation(tags = "Excel模块",summary = "查询导入进度")
    @GetMapping({"/importProgress/{dbformId}"})
    public BaseWebResult importProgress(@PathVariable("dbformId") Long dbformId, String batchCode, String handleResult) {
        String importTotalCouRedisKey = "excel:import_cou:total_" + batchCode ;//总条数
        String importTotalCouRedisKey_success = "excel:import_cou:success_" + batchCode ;//成功条数
        String importTotalCouRedisKey_fail = "excel:import_dcou:fail_" + batchCode ;//失败条数

        Object totalCouStr = lideeYunjiRedisUtils.get(importTotalCouRedisKey);
        Object successCouStr = lideeYunjiRedisUtils.get(importTotalCouRedisKey_success);
        Object failCouStr = lideeYunjiRedisUtils.get(importTotalCouRedisKey_fail);
        Long totalCou = Func.isEmpty(totalCouStr) ? 0 : Func.toLong(totalCouStr);
        Long successCou = Func.isEmpty(successCouStr) ? 0 : Func.toLong(successCouStr);
        Long failCou = Func.isEmpty(failCouStr) ? 0 : Func.toLong(failCouStr);

        if(Func.isEmpty(handleResult)){
            return BaseWebResult.success(totalCou);
        }
        if(Func.equals(handleResult,"SUCCESS")){
            return BaseWebResult.success(successCou);
        }
        if(Func.equals(handleResult,"FAIL")){
            return BaseWebResult.success(failCou);
        }
        return BaseWebResult.success(0);
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @ApiOperationSupport(order = 5)
    @Operation(tags = "Excel模块",summary = "操作 恢复/暂停/取消任务")
    @GetMapping({"/importOpTask/{dbformId}"})
    public BaseWebResult importOpTask(@PathVariable("dbformId") Long dbformId, Long batchCode, String taskState) {
        if (Func.equals(taskState, "START_TASK")) {//开启
            excelService.handleTempTable(dbformId, batchCode);
        } else {//暂停 取消
            String redisKey = "excel:import:task_" + batchCode;
            lideeYunjiRedisUtils.set(redisKey, taskState, 2, TimeUnit.DAYS);//存2天
        }

        return BaseWebResult.success("成功");
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @ApiOperationSupport(order = 6)
    @Operation(tags = "Excel模块",summary = "下载错误数据数据")
    @GetMapping({"/downloadErrorExcel/{dbformId}"})
    public void downloadErrorExcel(@PathVariable("dbformId") Long dbformId, Long batchCode, HttpServletResponse rsp) {
        //获取失败数据
        LambdaQueryWrapper<ExcelFileDataEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExcelFileDataEntity::getExcelFileId, batchCode);
        wrapper.eq(ExcelFileDataEntity::getHandleState, YNEnum.Y.getCode());
        wrapper.eq(ExcelFileDataEntity::getHandleResult, "FAIL");
        wrapper.orderByAsc(ExcelFileDataEntity::getSort);
        List<ExcelFileDataEntity> entityList = excelDataService.list(wrapper);

        List<Map<String, Object>> dataMapList = new ArrayList<>();
        for (ExcelFileDataEntity entity : entityList) {
            String dataJson = entity.getDataJson();
            Map<String, Object> dataMap = Func.json2Bean(dataJson, Map.class);
            dataMap.put("error_reason", entity.getErrorReason());
            dataMapList.add(dataMap);
        }


        MoreSheetConfig excelTemplateModel = super.exportExcelTemplate(dbformId);
        LinkedMap<String, ExcelTitleModel> headTitleMap = excelTemplateModel.getHeadMap();
        //加入错误原因
        ExcelTitleModel titleModel = new ExcelTitleModel();
        titleModel.setTitle("错误原因");
        headTitleMap.put("error_reason", titleModel);

        //导出
        lideeYunJiExcelUtils.exportExcel(rsp, excelTemplateModel.getSheetName(), headTitleMap, dataMapList);

    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @PostMapping("/run/import/{dbformId}")
    @ApiOperationSupport(order = 7)
    @Operation(tags = "Excel模块",summary = "开始导入")
    public BaseWebResult runImport(@PathVariable("dbformId") Long dbformId, Long batchCode) {
        try {
            //封装参数
            ButtonParamImport buttonParam = new ButtonParamImport();
            buttonParam.setDbFormId(dbformId);
            buttonParam.setBatchCode(batchCode);
            buttonParam.setServiceType("HANBLE_TEMPLATE");//业务类型
            super.importExcelData(buttonParam);
        } catch (Exception e) {
            throw new lideeYunJiException("导入失败");
        }
        return BaseWebResult.success("成功");
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @PostMapping("/view/page/{dbformId}")
    @ApiOperationSupport(order = 7)
    @Operation(tags = "Excel模块",summary = "数据预览(分页)")
    public BaseWebResult page(@PathVariable("dbformId") Long dbformId, String handleResult,Long batchCode, PageVo pageVo) {
        Page page = FuncWeb.getPage(pageVo.getPageNo(), pageVo.getPageSize());
        LambdaQueryWrapper<ExcelFileDataEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExcelFileDataEntity::getExcelFileId, batchCode);//batchCode就是id
        wrapper.eq(Func.isNotEmpty(handleResult),ExcelFileDataEntity::getHandleResult,handleResult);
        wrapper.orderByAsc(ExcelFileDataEntity::getSort);
        IPage<ExcelFileDataEntity> pages = excelDataService.page(page, wrapper);
        return BaseWebResult.success(pages);
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @PostMapping("/update/fileData/{dbformId}")
    @ApiOperationSupport(order = 7)
    @Operation(tags = "Excel模块",summary = "修改值")
    public BaseWebResult updateFileData(@PathVariable("dbformId") Long dbformId, @RequestBody UpdateFileDataParam param) {
        ExcelFileDataEntity updateEntity = new ExcelFileDataEntity();
        updateEntity.setId(param.getId());
        updateEntity.setDataJson(param.getJsonStr());
        excelDataService.updateById(updateEntity);
        return BaseWebResult.success("成功");
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @PostMapping("/del/fileData/{dbformId}")
    @ApiOperationSupport(order = 7)
    @Operation(tags = "Excel模块",summary = "删除值")
    public BaseWebResult delFileData(@PathVariable("dbformId") Long dbformId, @RequestBody UpdateFileDataParam param) {
        excelDataService.delById(param.getId());
        return BaseWebResult.success("成功");
    }


    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @PostMapping("/file/list/{dbformId}")
    @ApiOperationSupport(order = 7)
    @Operation(tags = "Excel模块",summary = "获取导入列表")
    public BaseWebResult fileList(@PathVariable("dbformId") Long dbformId, PageVo pageVo) {
        Long tenantId = lideeYunJiAdapter.getTenantId();
        Integer excelFileDataDay = lideeYunjiProperties.getExcelDay();

        Page page = FuncWeb.getPage(pageVo.getPageNo(), pageVo.getPageSize());

        LambdaQueryWrapper<ExcelFileEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExcelFileEntity::getDbformId, dbformId);
        wrapper.eq(ExcelFileEntity::getTenantId, tenantId);
        wrapper.orderByDesc(ExcelFileEntity::getId);
        Page pages = excelFileService.page(page, wrapper);
        List<ExcelFileEntity> records = pages.getRecords();
        if (Func.isNotEmpty(records)) {
            for (ExcelFileEntity fileEntity : records) {
                Long fileId = fileEntity.getId();//文件id
                //判断是否有数据
                LambdaQueryWrapper<ExcelFileDataEntity> wrapperData = new LambdaQueryWrapper<>();
                wrapperData.eq(ExcelFileDataEntity::getExcelFileId, fileId);
                long count = excelDataService.count(wrapperData);
                fileEntity.setViewFlag(count > 0);
            }
        }
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("day",excelFileDataDay);
        resultMap.put("pages",pages);
        return BaseWebResult.success(resultMap);
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:dbform-data:import:'+#dbformId)")
    @PostMapping("/rollback/{dbformId}")
    @ApiOperationSupport(order = 7)
    @Operation(tags = "Excel模块",summary = "撤回(只允许本人撤销)")
    public BaseWebResult fileList(@PathVariable("dbformId") Long dbformId, Long batchCode) {
        LambdaQueryWrapper<ExcelFileEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExcelFileEntity::getDbformId, dbformId);
        wrapper.eq(ExcelFileEntity::getId, batchCode);
        wrapper.eq(ExcelFileEntity::getCreateUser, lideeYunJiAdapter.getOnlineUserId());
        ExcelFileEntity excelFileEntity = excelFileService.getOne(wrapper);
        if (Func.isEmpty(excelFileEntity)) {
            return BaseWebResult.error(FrameErrorCodeConstants.FRAME_IMPORT_EXCEL_NOT_DATA);
        }
        String importState = excelFileEntity.getImportState();
        if (Func.isNotEmpty(importState) && Func.notEquals(importState, "1")) {
            return BaseWebResult.error(FrameErrorCodeConstants.FRAME_IMPORT_EXCEL_STATE_ERROR);
        }
        //进行撤回
        excelFileService.rollback(excelFileEntity.getId());

        return BaseWebResult.success("成功");
    }

    @PreAuthorize("@ss.hasPermission('lideeyunji:report-data:export:'+#reportCode)")
    @ApiOperationSupport(order = 2)
    @Operation(tags = "Excel模块",summary = "导出报表数据")
    @PostMapping({"/exportReport/{reportCode}"})
    public void exportReportData(@PathVariable("reportCode") String reportCode, HttpServletRequest req, HttpServletResponse rsp) {
        Map<String, Object> params = FuncWeb.getParameterBodyMap(req);
        List<MoreSheetConfig> sheetList = super.exportReportData(reportCode, params);
        String sheetName="数据导出";
        if(Func.isNotEmpty(sheetList)){
            sheetName=sheetList.get(0).getSheetName();
        }
        //导出
        lideeYunJiExcelUtils.exportExcel(rsp, sheetName,sheetList);
    }
}
