package com.yeejoin.amos.boot.module.jcs.biz.controller;

import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.api.R;
import com.yeejoin.amos.boot.biz.common.excel.TemplateCellWriteHandler;
import com.yeejoin.amos.boot.biz.common.excel.TemplateCellWriteHandlerDate;
import com.yeejoin.amos.boot.module.common.api.dto.*;
import com.yeejoin.amos.boot.module.common.api.enums.ExceptionEnum;
import com.yeejoin.amos.boot.module.common.api.excel.*;
import com.yeejoin.amos.boot.module.common.biz.service.impl.WaterResourceServiceImpl;
import org.apache.commons.jexl2.UnifiedJEXL;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.typroject.tyboot.core.foundation.enumeration.UserType;
import org.typroject.tyboot.core.restful.doc.TycloudOperation;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseHelper;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import com.baomidou.mybatisplus.core.toolkit.Sequence;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.controller.BaseController;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.jcs.api.enums.ExcelEnums;
import com.yeejoin.amos.boot.module.jcs.biz.service.impl.DataSourcesImpl;
import com.yeejoin.amos.boot.module.jcs.biz.service.impl.ExcelServiceImpl;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * 导出导入
 *
 * @author system_generator
 * @date 2021-06-29
 */
@RestController
@Api(tags = "导出")
@RequestMapping(value = "/excel")
public class ExcelController extends BaseController {

	@Autowired
	ExcelServiceImpl excelService;

	@Autowired
	DataSourcesImpl dataSources;

	@Autowired
	RedisUtils redisUtils;

	@Autowired
	Sequence sequence;

	@Autowired
	WaterResourceServiceImpl waterResourceServiceImpl;

    @Value("${logic}")
    private Boolean logic ;


	private static String JCDWRY = "JCDWRY";
	private static String DLDWRY = "DLDWRY";
	//同步机场单位
    private static String JCDWRYTP = "JCDWRYTP";

	@TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "获取上传excle文件是否成功")
	@GetMapping("/get/template/isSuccess/{key}")
	public ResponseModel<Object> getTemplateIsSuccess(HttpServletResponse response,
			@PathVariable(value = "key") String key) {
		if (redisUtils.hasKey(key)) {
			Object obj = redisUtils.get(key);
			return ResponseHelper.buildResponse(obj);
		}
		return ResponseHelper.buildResponse(null);
	}

	@TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "下载模板")
	@GetMapping("/download/template/{type}")
	public void downloadTemplate(HttpServletResponse response, @PathVariable(value = "type") String type) {
		try {
			if(type.equals(JCDWRY) && logic != null&& !logic){
				type = DLDWRY;
			}
			ExcelEnums excelEnums = ExcelEnums.getByKey(type);
			ExcelDto excelDto = new ExcelDto(excelEnums.getFileName(), excelEnums.getSheetName(),
					excelEnums.getClassUrl(), excelEnums.getType());
			excelService.templateExport(response, excelDto);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BadRequest(ExceptionEnum.PARAMETER_TYPE_ERR.getEmsg());
		}
	}

	/**
	 * * @param Map par 可以传递过滤条件，传入具体实现类中
	 *
	 * @return
	 *
	 *         <PRE>
	 * author tw
	 * date 2021/9/13
	 *         </PRE>
	 */
	@TycloudOperation(needAuth = false,ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "导出公用类")
	@GetMapping("/export/{type}")
	public void getFireStationFile(HttpServletResponse response, @PathVariable(value = "type") String type,
			@RequestParam Map<String,Object> par) {
		try {
			if(type.equals(JCDWRY) && logic != null &&!logic){
				type = DLDWRY;
			}
			ExcelEnums excelEnums = ExcelEnums.getByKey(type);
			ExcelDto excelDto = new ExcelDto(excelEnums.getFileName(), excelEnums.getSheetName(),
					excelEnums.getClassUrl(), excelEnums.getType());
			excelService.commonExport(response, excelDto, par);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BadRequest(ExceptionEnum.PARAMETER_TYPE_ERR.getEmsg());
		}
	}

	@TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "导入公用")
	@PostMapping("/upload/{type}")
	public ResponseModel<Object> upload(@RequestPart("file") MultipartFile multipartFile,
			@PathVariable(value = "type") String type,HttpServletRequest equest) {
		try {
			long uuid = sequence.nextId();
			String uuidString = Long.toString(uuid);
			redisUtils.set(uuidString, 0);
			if(type.equals(JCDWRY) && logic !=null && !logic){
				type = DLDWRY;
			}
			ExcelEnums excelEnums = ExcelEnums.getByKey(type);
			ExcelDto excelDto = new ExcelDto(excelEnums.getFileName(), excelEnums.getSheetName(),
					excelEnums.getClassUrl(), excelEnums.getType());
			excelService.commonUpload(multipartFile, excelDto, uuidString,equest);
			return ResponseHelper.buildResponse(uuidString);
		} catch (RuntimeException e) {
			e.printStackTrace();
			throw new BadRequest(e.getMessage());
		} catch (Exception e) {
			throw new BadRequest("文件格式不正确或excel 模板不匹配！");
		}

	}

	/**
	 * 导出值班模板
	 *
	 * @param response
	 * @param beginDate 值班开始日期
	 * @param endDate   值班结束日期
	 * @param excelDto  导出类型参数
	 * @param ids       部门或队伍的id列表，逗号分隔
	 */
	@TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "导出值班模板", notes = "导出值班模板")
	@PostMapping (value = "/duty_template")
	public void dutyCarTemplate(HttpServletResponse response, @RequestParam("beginDate") String beginDate,
			@RequestParam("endDate") String endDate, ExcelDto excelDto, @RequestBody String ids) {
		try {
			if(org.apache.commons.lang3.StringUtils.isNotEmpty(ids)) {
				ids = ids.substring(1,ids.length()-1);
				excelService.dutyTemplateExport(response, beginDate, endDate, excelDto, ids);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new BadRequest(ExceptionEnum.PARAMETER_TYPE_ERR.getEmsg());
		}
	}

	@TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "导出值班信息", notes = "导出值班模板")
	@GetMapping(value = "/duty_info")
	public void dutyCarDuty(HttpServletResponse response, @RequestParam("beginDate") String beginDate,
			@RequestParam("endDate") String endDate, ExcelDto excelDto) {
		try {
			excelService.dutyInfoExport(response, beginDate, endDate, excelDto);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BadRequest(ExceptionEnum.PARAMETER_TYPE_ERR.getEmsg());
		}
	}

	@TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "导出公用类带过滤参数")
	@PostMapping("/exportByParams/{type}")
	public void getFireStationFileByParams(HttpServletResponse response, @PathVariable(value = "type") String type,
			@RequestParam(value = "params") String params) {
		try {
			ExcelEnums excelEnums = ExcelEnums.getByKey(type);
			ExcelDto excelDto = new ExcelDto(excelEnums.getFileName(), excelEnums.getSheetName(),
					excelEnums.getClassUrl(), excelEnums.getType());
			excelService.exportByParams(response, excelDto, params);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BadRequest(ExceptionEnum.PARAMETER_TYPE_ERR.getEmsg());
		}
	}

	@TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "导出给提供设备接口")
	@GetMapping(value = "/exportForEquipment")
	public ResponseModel<String[]> getFireStationFileByParams(String type, String method) {
		try {
			return ResponseHelper.buildResponse(dataSources.selectList(type, method));
		} catch (Exception e) {
			e.printStackTrace();
			throw new BadRequest(ExceptionEnum.PARAMETER_TYPE_ERR.getEmsg());
		}
	}

    @TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
    @ApiOperation(value = "获取导入接口")
    @GetMapping(value = "/getexport/{key}")
    public ResponseModel<Object> getexport(@PathVariable(value = "key")String key) {
       Object ob= redisUtils.get(key);
      return ResponseHelper.buildResponse(ob);
    }


    @TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
    @ApiOperation(value = "导入公用")
    @PostMapping("/uploadNew")
    public ResponseModel<Object> uploadNew(@RequestPart("file") MultipartFile multipartFile,
                                        HttpServletRequest equest) {
        try {
            ExcelEnums excelEnums = ExcelEnums.getByKey(JCDWRYTP);
            ExcelDto excelDto = new ExcelDto(excelEnums.getFileName(), excelEnums.getSheetName(),
                    excelEnums.getClassUrl(), excelEnums.getType());
            Object ob=excelService.commonUpload(multipartFile, excelDto, null,equest);
            return ResponseHelper.buildResponse(ob);
        } catch (RuntimeException e) {
            e.printStackTrace();
            throw new BadRequest(e.getMessage());
        } catch (Exception e) {
            throw new BadRequest("文件格式不正确或excel 模板不匹配！");
        }

    }

    @TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
    @ApiOperation(value = "下载模板")
    @GetMapping("/downloadnew/template")
    public void downloadnew(HttpServletResponse response) {
        try {
            ExcelEnums excelEnums = ExcelEnums.getByKey(JCDWRYTP);
            ExcelDto excelDto = new ExcelDto(excelEnums.getFileName(), excelEnums.getSheetName(),
                    excelEnums.getClassUrl(), excelEnums.getType());
            excelService.templateExport(response, excelDto);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequest(ExceptionEnum.PARAMETER_TYPE_ERR.getEmsg());
        }
    }


	@TycloudOperation(ApiLevel = UserType.AGENCY)
	@RequestMapping(value = "/downTempdelate", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "水源模板下载", notes = "水源模板下载")
	public void downTempdelate(HttpServletResponse response) {
		try {
			response.setCharacterEncoding("UTF-8");
			response.setHeader("content-Type", "application/vnd.ms-excel");
			response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("消防水源模板.xlsx", "UTF-8"));
			response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");

			Map<Integer, ExcelSelectedResolve> resolveMap = ExcelUtil.resolveSelectedAnnotation(WaterBaseResourceDto.class, dataSources);
			ExcelWriter excelWriter = EasyExcelFactory.write(response.getOutputStream()).registerWriteHandler(new SelectedSheetWriteHandler(resolveMap)).registerWriteHandler(new TemplateCellWriteHandler()).build();

			List<WaterExcelPoolDto> waterExcelPoolDtos = new ArrayList<>();
			Map<Integer, ExcelSelectedResolve> resolveMap1 = ExcelUtil.resolveSelectedAnnotation(WaterExcelPoolDto.class, dataSources);
			WriteSheet writeSheet = EasyExcelFactory.writerSheet(0, "消防水池" ).head(WaterExcelPoolDto.class).head(WaterExcelPoolDto.class).registerWriteHandler(new SelectedSheetWriteHandler(resolveMap1)).build();

			List<WaterExcelHydrantDto> waterExcelHydrantDtos = new ArrayList<>();
			Map<Integer, ExcelSelectedResolve> resolveMap2 = ExcelUtil.resolveSelectedAnnotation(WaterExcelHydrantDto.class, dataSources);
			WriteSheet writeSheet2 = EasyExcelFactory.writerSheet(1, "消火栓").head(WaterExcelHydrantDto.class).registerWriteHandler(new SelectedSheetWriteHandler(resolveMap2)).registerWriteHandler(new TemplateCellWriteHandler()).build();

			List<WaterExcelCraneDto> waterExcelCraneDtos = new ArrayList<>();
			Map<Integer, ExcelSelectedResolve> resolveMap3 = ExcelUtil.resolveSelectedAnnotation(WaterExcelCraneDto.class, dataSources);
			WriteSheet writeSheet3 = EasyExcelFactory.writerSheet(2, "消防水鹤").head(WaterExcelCraneDto.class).registerWriteHandler(new SelectedSheetWriteHandler(resolveMap3)).registerWriteHandler(new TemplateCellWriteHandler()).build();

			List<WaterExcelNaturalDto> waterExcelNaturalDtos = new ArrayList<>();
			Map<Integer, ExcelSelectedResolve> resolveMap4= ExcelUtil.resolveSelectedAnnotation(WaterExcelNaturalDto.class, dataSources);
			WriteSheet writeSheet4 = EasyExcelFactory.writerSheet(3, "天然水源").head(WaterExcelNaturalDto.class).registerWriteHandler(new SelectedSheetWriteHandler(resolveMap4)).registerWriteHandler(new TemplateCellWriteHandler()).build();

			Map<Integer, ExcelSelectedResolve> resolveMap5= ExcelUtil.resolveSelectedAnnotation(WaterExcelIndustryPoolDto.class, dataSources);
			List<WaterExcelIndustryPoolDto> waterExcelIndustryPoolDtos = new ArrayList<>();
			WriteSheet writeSheet5 = EasyExcelFactory.writerSheet(4, "工业水池").head(WaterExcelIndustryPoolDto.class).registerWriteHandler(new SelectedSheetWriteHandler(resolveMap5)).registerWriteHandler(new TemplateCellWriteHandler()).build();

			List<WaterExcelWaterTankDto> waterExcelWaterTankDtos = new ArrayList<>();
			Map<Integer, ExcelSelectedResolve> resolveMap6= ExcelUtil.resolveSelectedAnnotation(WaterExcelWaterTankDto.class, dataSources);
			WriteSheet writeSheet6 = EasyExcelFactory.writerSheet(5, "消防水箱").head(WaterExcelWaterTankDto.class).registerWriteHandler(new SelectedSheetWriteHandler(resolveMap6)).registerWriteHandler(new TemplateCellWriteHandler()).build();


			excelWriter.write(waterExcelPoolDtos, writeSheet);
			excelWriter.write(waterExcelHydrantDtos, writeSheet2);
			excelWriter.write(waterExcelCraneDtos, writeSheet3);
			excelWriter.write(waterExcelNaturalDtos, writeSheet4);
			excelWriter.write(waterExcelIndustryPoolDtos, writeSheet5);
			excelWriter.write(waterExcelWaterTankDtos, writeSheet6);

			excelWriter.finish();
			response.flushBuffer();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@TycloudOperation(ApiLevel = UserType.AGENCY)
	@RequestMapping(value = "/exportData", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "水源导出", notes = "水源导出")
	public void exportData(HttpServletResponse response) {
		try {
			response.setCharacterEncoding("UTF-8");
			response.setHeader("content-Type", "application/vnd.ms-excel");
			response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("消防水源.xlsx", "UTF-8"));
			response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");

			List<WaterExcelPoolDto> waterExcelPoolDtos = new ArrayList<>();
			List<WaterExcelHydrantDto> waterExcelHydrantDtos = new ArrayList<>();
			List<WaterExcelCraneDto> waterExcelCraneDtos = new ArrayList<>();
			List<WaterExcelNaturalDto> waterExcelNaturalDtos = new ArrayList<>();
			List<WaterExcelWaterTankDto> waterExcelWaterTankDtos = new ArrayList<>();
			List<WaterExcelIndustryPoolDto> waterExcelIndustryPoolDtos = new ArrayList<>();

			List<WaterResourceForExportDto> waterResourceDtoList = waterResourceServiceImpl.exportToExcel(true,null,null,null);
			waterResourceDtoList.forEach(e->{
				switch (e.getResourceType()){
					case "hydrant" :
						WaterExcelHydrantDto waterExcelHydrantDto = new WaterExcelHydrantDto();
						BeanUtils.copyProperties(e,waterExcelHydrantDto);
						waterExcelHydrantDtos.add(waterExcelHydrantDto);
						break;
					case "crane" :
						WaterExcelCraneDto waterExcelCraneDto = new WaterExcelCraneDto();
						BeanUtils.copyProperties(e,waterExcelCraneDto);
						waterExcelCraneDtos.add(waterExcelCraneDto);
						break;
					case "pool" :
						WaterExcelPoolDto waterExcelPoolDto = new WaterExcelPoolDto();
						BeanUtils.copyProperties(e,waterExcelPoolDto);
						waterExcelPoolDtos.add(waterExcelPoolDto);
						break;
					case "natural" :
						WaterExcelNaturalDto waterExcelNaturalDto = new WaterExcelNaturalDto();
						BeanUtils.copyProperties(e,waterExcelNaturalDto);
						waterExcelNaturalDtos.add(waterExcelNaturalDto);
						break;
					case "industryPool" :
						WaterExcelIndustryPoolDto waterExcelIndustryPoolDto = new WaterExcelIndustryPoolDto();
						BeanUtils.copyProperties(e,waterExcelIndustryPoolDto);
						waterExcelIndustryPoolDtos.add(waterExcelIndustryPoolDto);
						break;
					case "waterTank" :
						WaterExcelWaterTankDto waterExcelWaterTankDto = new WaterExcelWaterTankDto();
						BeanUtils.copyProperties(e,waterExcelWaterTankDto);
						waterExcelWaterTankDtos.add(waterExcelWaterTankDto);
						break;
				}
			});


			ExcelWriter excelWriter = EasyExcelFactory.write(response.getOutputStream()).build();
			WriteSheet writeSheet = EasyExcelFactory.writerSheet(0, "消防水池" ).head(WaterExcelPoolDto.class).build();
			WriteSheet writeSheet2 = EasyExcelFactory.writerSheet(1, "消火栓").head(WaterExcelHydrantDto.class).build();
			WriteSheet writeSheet3 = EasyExcelFactory.writerSheet(2, "消防水鹤").head(WaterExcelCraneDto.class).build();
			WriteSheet writeSheet4 = EasyExcelFactory.writerSheet(3, "天然水源").head(WaterExcelNaturalDto.class).build();
			WriteSheet writeSheet5 = EasyExcelFactory.writerSheet(4, "工业水池").head(WaterExcelIndustryPoolDto.class).build();
			WriteSheet writeSheet6 = EasyExcelFactory.writerSheet(5, "消防水箱").head(WaterExcelWaterTankDto.class).build();


			excelWriter.write(waterExcelPoolDtos, writeSheet);
			excelWriter.write(waterExcelHydrantDtos, writeSheet2);
			excelWriter.write(waterExcelCraneDtos, writeSheet3);
			excelWriter.write(waterExcelNaturalDtos, writeSheet4);
			excelWriter.write(waterExcelIndustryPoolDtos, writeSheet5);
			excelWriter.write(waterExcelWaterTankDtos, writeSheet6);

			excelWriter.finish();
			response.flushBuffer();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@TycloudOperation(needAuth = false, ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "水源信息导入")
	@PostMapping("/upload/waterResource")
	public ResponseModel<Object> uploadWaterResource(@RequestPart("file") MultipartFile multipartFile) {

		try {
		excelService.excelImportWaterResourceNew(multipartFile);
			return ResponseHelper.buildResponse("导入成功");
		} catch (RuntimeException e) {
			e.printStackTrace();
			throw new BadRequest(e.getMessage());
		} catch (Exception e) {
			throw new BadRequest("文件格式不正确或excel 模板不匹配！");
		}

	}

	private Map<Integer, String[]> resolveExplicitConstraint(Class<?> model, DataSources dataDictionaryMapper) {
		Map<Integer, String[]> explicitListConstraintMap = new HashMap<>();

			// 循环获取对应列得下拉列表信息
			Field[] declaredFields = model.getDeclaredFields();
			for (int i = 0; i < declaredFields.length; i++) {
				Field field = declaredFields[i];
				// 解析注解信息
				ExplicitConstraint explicitConstraint = field.getAnnotation(ExplicitConstraint.class);
				ExcelUtil.resolveExplicitConstraint(explicitListConstraintMap, explicitConstraint, dataDictionaryMapper);

		}
		return explicitListConstraintMap;
	}




}
