package com.emergency.avenue.storage.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.emergency.avenue.admin.api.entity.SysDeptRelation;
import com.emergency.avenue.admin.api.entity.SysTreeDict;
import com.emergency.avenue.admin.exception.MyCustomException;
import com.emergency.avenue.admin.service.SysDeptRelationService;
import com.emergency.avenue.admin.service.SysTreeDictService;
import com.emergency.avenue.common.core.constant.FieldParam;
import com.emergency.avenue.common.core.constant.TranslationDict;
import com.emergency.avenue.common.core.util.R;
import com.emergency.avenue.common.excel.EasyExcelUtil;
import com.emergency.avenue.common.excel.annotation.RequestExcel;
import com.emergency.avenue.common.log.annotation.SysLog;
import com.emergency.avenue.common.security.util.SecurityUtils;
import com.emergency.avenue.storage.api.entity.OutboundInfo;
import com.emergency.avenue.storage.api.entity.OutboundMaterialInfo;
import com.emergency.avenue.storage.api.entity.OutboundStatus;
import com.emergency.avenue.storage.api.request.OutboundInfoRequest;
import com.emergency.avenue.storage.api.response.OutbountInfoResponse;
import com.emergency.avenue.storage.api.vo.OutbountExcelVO;
import com.emergency.avenue.storage.service.OutboundMaterialService;
import com.emergency.avenue.storage.service.OutboundService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@RestController
@AllArgsConstructor
@RequestMapping("/out")
@Tag(description = "outbound", name = "出库信息管理")
public class OutboundInfoController {
	private final OutboundService outboundService;

	private final OutboundMaterialService outboundMaterialService;

	private final SysTreeDictService sysTreeDictService;

	private final SysDeptRelationService relationService;


	@GetMapping("/page")
	@Operation(description = "出库分页查询", summary = "出库分页查询")
	public R<Page<OutboundInfo>> getOutboundPage(Page<OutboundInfo> page, OutboundInfo outboundInfo) {
		Page<OutboundInfo> page1 = getOutboundInfoPage(page, outboundInfo);
		return R.ok(page1);
	}

	/**
	 * 出库信息下发-导出模板.xlsx
	 */
	@GetMapping("/exportcjxxxf")
	@Operation(description = "救灾调用物资统计表-导出excel", summary = "救灾调用物资统计表-导出excel")
	public void exportcjxxxf(Page<OutboundInfo> page, OutboundInfo outboundInfo,
							 HttpServletResponse response) {
		page = new Page<>(-1,-1);
		Page<OutboundInfo> page1 = getOutboundInfoPage(page, outboundInfo);

		String fileName = "exportcjxxxf.xlsx";
		String templateFile = "出库信息下发-导出模板.xlsx";
		try {
			outboundMaterialService.exportcjxxxf(fileName,templateFile, page1.getRecords(),response);
		} catch (MyCustomException e) {
			throw new RuntimeException("导出失败");
		}
	}

	@NotNull
	private Page<OutboundInfo> getOutboundInfoPage(Page<OutboundInfo> page, OutboundInfo outboundInfo) {
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		QueryWrapper<OutboundInfo> query = Wrappers.query(outboundInfo);
		query.lambda().in(OutboundInfo::getDeptId,deptIds);
		if(StringUtils.isEmpty(outboundInfo.getLower())){
			query.lambda().ne(OutboundInfo::getStatus,"8");
			String deptType = SecurityUtils.getUser().getDeptType();
			if (deptType.equals("2")) {
				query.lambda().ne(OutboundInfo::getStatus,"1");
				query.orderByAsc("FIELD(status,'2','6','3','4','5','7')");
			}else if (deptType.equals("1")){
				query.lambda().notIn(OutboundInfo::getStatus, Arrays.asList("1","2","4","7"));
				query.lambda().orderByAsc(OutboundInfo::getStatus);
			}else if (deptType.equals("3")){
				query.orderByAsc("FIELD(status,'4','1','7','2','3','5','6')");
			}
		}else{
			query.lambda().in(OutboundInfo::getStatus,Arrays.asList("8","7"));
			query.orderByAsc("FIELD(status,'8','7')");
		}
		if (StringUtils.isNotEmpty(outboundInfo.getMaterialNameVo())) {
			QueryWrapper<SysTreeDict> queryWrapper = new QueryWrapper<>();
			queryWrapper.lambda().eq(SysTreeDict::getType,"1");
			queryWrapper.lambda().like(SysTreeDict::getName,outboundInfo.getMaterialNameVo());
			List<SysTreeDict> list1 = sysTreeDictService.list(queryWrapper);
			List<String> collect = list1.stream().map(SysTreeDict::getId).collect(Collectors.toList());
			if (collect.size()<1){
				return page;
			}
			query.lambda().in(OutboundInfo::getMaterialName,collect);
		}
		query.lambda().orderByDesc(OutboundInfo::getSubmitTime);
		Page<OutboundInfo> page1 = outboundService.page(page, query);
		List<SysTreeDict> list = sysTreeDictService.getList(1);
		Map<String, String> collect = list.stream().collect(Collectors.toMap(SysTreeDict::getId, SysTreeDict::getName));
		List<OutboundInfo> records = page1.getRecords();
		for (OutboundInfo outboundInfo1:records){
			outboundInfo1.setMaterialGroup(collect.get(outboundInfo1.getMaterialGroup()));
			outboundInfo1.setMaterialType(collect.get(outboundInfo1.getMaterialType()));
			outboundInfo1.setMaterialName(collect.get(outboundInfo1.getMaterialName()));
		}
		return page1;
	}

	@GetMapping("/material/page")
	@Operation(description = "出库分页查询(用于首页出库下发)", summary = "出库分页查询(用于首页出库下发)")
	public R<Page<OutboundMaterialInfo>> getOutboundMaterialPage(Page<OutboundMaterialInfo> page, OutboundInfo outboundInfo) {
		QueryWrapper<OutboundInfo> query = Wrappers.query(outboundInfo);
		query.lambda().eq(OutboundInfo::getDeptId,SecurityUtils.getUser().getDeptId());
		query.lambda().ne(OutboundInfo::getStatus,"7");
		List<Integer> collect1 = outboundService.list(query).stream().map(OutboundInfo::getOutboundId).collect(Collectors.toList());
		if (collect1.size()==0){
			return R.ok(page);
		}
		QueryWrapper<OutboundMaterialInfo> querym=new QueryWrapper<>();
		querym.lambda().in(OutboundMaterialInfo::getOutboundId,collect1);
		querym.lambda().orderByAsc(OutboundMaterialInfo::getOutboundTime);
		Page<OutboundMaterialInfo> page1 = outboundMaterialService.page(page, querym);
		List<OutboundMaterialInfo> records = page1.getRecords();
		List<SysTreeDict> list = sysTreeDictService.getList(1);
		Map<String, String> collect = list.stream().collect(Collectors.toMap(SysTreeDict::getId, SysTreeDict::getName));
		for (OutboundMaterialInfo outboundMaterialInfo:records){
			outboundMaterialInfo.setMaterialGroup(collect.get(outboundMaterialInfo.getMaterialGroup()));
			outboundMaterialInfo.setMaterialType(collect.get(outboundMaterialInfo.getMaterialType()));
			outboundMaterialInfo.setMaterialName(collect.get(outboundMaterialInfo.getMaterialName()));
			outboundMaterialInfo.setUnit(collect.get(outboundMaterialInfo.getUnit()));
		}
		return R.ok(page1);
	}
	/**
	 * 通过ID查询出库信息
	 * @param id ID
	 * @return 出库信息
	 */
	@GetMapping("/{id}")
	@Operation(description = "通过ID查询出库信息", summary = "通过ID查询出库信息")
	public R<OutboundInfo> getById(@PathVariable Integer id) {
		return R.ok(outboundService.getById(id));
	}


	/**
	 * 通过表信息id查找
	 * @param id 出库信息表
	 * @return 信息
	 */
	@GetMapping("/outdound/{id}")
	@Operation(description = "通过表信息id查找", summary = "通过表信息id查找")
	public R<Map<Object, Object>> getDictByType(@PathVariable Integer id) {
		return outboundMaterialService.listMap(id);
	}


	@SysLog("添加出库信息")
	@PostMapping
	@Operation(description = "添加出库信息", summary = "添加出库信息")
	public R save(@RequestBody OutboundInfo outboundInfo) {
		return outboundService.saveOutbountAndMaterial(outboundInfo);
	}


	@SysLog("删除出库信息")
	@DeleteMapping("/{id}")
	@Operation(description = "删除出库信息", summary = "删除出库信息")
	public R<Boolean> removeById(@PathVariable Long id) {
		outboundMaterialService.remove(Wrappers.<OutboundMaterialInfo>query().lambda().eq(OutboundMaterialInfo::getOutboundId, id));
		return R.ok(outboundService.removeById(id));
	}

	/**
	 * 修改出库信息
	 * @param outboundInfo 出库信息信息
	 * @return success/false
	 */
	@PutMapping
	@SysLog("修改出库信息")
	@Operation(description = "修改出库信息", summary = "修改出库信息")
	public R<R> updateById(@RequestBody OutboundInfo outboundInfo) {
		return R.ok(outboundService.updateOutbountAndMaterial(outboundInfo));
	}

	@PutMapping("/auditing")
	@Operation(description = "审核出库信息", summary = "审核出库信息")
	public R auditing(@RequestBody OutboundStatus outboundStatus) {
		return outboundMaterialService.saveOutboundStatus(outboundStatus);
	}

	@GetMapping("/aduicount")
	@Operation(description = "待审核条数 用于首页", summary = "待审核条数 用于首页")
	public R selectOutAndInAudi(){
      return outboundService.selectOutAndInAudi();
	}


	@PostMapping("/selectDistributeListByMaterials")
	@Operation(description = "查询出库下发明细(按调用物资)", summary = "查询出库下发明细(按调用物资)")
	@TranslationDict({
			@FieldParam(dictType = "province_ch", targetField = "province")
	})
    public R selectDistributeListByMaterials(@RequestBody OutboundInfoRequest outboundInfoRequest){
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		outboundInfoRequest.setDeptIdList(deptIds);
		return outboundMaterialService.selectDistributeListByMaterials(outboundInfoRequest);
	}

	/**
	 * 救灾调用物资统计表-导出模板.xlsx
	 */
	@PostMapping("/exportjzdywztjb")
	@Operation(description = "救灾调用物资统计表-导出excel", summary = "救灾调用物资统计表-导出excel")
	public void exportjzdywztjb(@RequestBody OutboundInfoRequest outboundInfoRequest,
								HttpServletResponse response) {
		R<List<OutbountInfoResponse>> listR = selectDistributeListByMaterials(outboundInfoRequest);

		String fileName = "exportjzdywztjb.xlsx";
		String templateFile = "救灾调用物资统计表-导出模板.xlsx";
		try {
			 outboundMaterialService.exportjzdywztjb(fileName,templateFile, listR.getData(),response);
		} catch (MyCustomException e) {
			throw new RuntimeException("导出失败");
		}
	}

	@PostMapping("/selectDistributeListByProvince")
	@Operation(description = "查询出库下发明细(按调用省份)", summary = "查询出库下发明细(按调用省份)")
	@TranslationDict({
			@FieldParam(dictType = "province_ch", targetField = "province")
	})
	public R selectDistributeListByProvince(@RequestBody OutboundInfoRequest outboundInfoRequest){
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		outboundInfoRequest.setDeptIdList(deptIds);
		return outboundMaterialService.selectDistributeListByProvince(outboundInfoRequest);
	}

	/**
	 * 救灾调用省份统计表-导出模板.xlsx
	 */
	@PostMapping("/exportjzdysftjb")
	@Operation(description = "救灾调用省份统计表-导出excel", summary = "救灾调用省份统计表-导出excel")
	public void exportjzdysftjb(@RequestBody OutboundInfoRequest outboundInfoRequest,
								HttpServletResponse response) {
		R<List<OutbountInfoResponse>> listR = selectDistributeListByProvince(outboundInfoRequest);

		String fileName = "exportjzdysftjb.xlsx";
		String templateFile = "救灾调用省份统计表-导出模板.xlsx";
		try {
			outboundMaterialService.exportjzdysftjb(fileName,templateFile, listR.getData(),response);
		} catch (MyCustomException e) {
			throw new RuntimeException("导出失败");
		}
	}



	@PostMapping("/selectDistributeListByWarehouse")
	@Operation(description = "查询出库下发明细(按调出仓库)", summary = "查询出库下发明细(按调出仓库)")
	@TranslationDict({
			@FieldParam(dictType = "province_ch", targetField = "province"),
			@FieldParam(dictType = "province_ch", targetField = "outProvince")
	})
	public R selectDistributeListByWarehouse(@RequestBody OutboundInfoRequest outboundInfoRequest){
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		outboundInfoRequest.setDeptIdList(deptIds);
		return outboundMaterialService.selectDistributeListByWarehouse(outboundInfoRequest);
	}

	/**
	 * 救灾调出仓库统计表-导出模板.xlsx
	 */
	@PostMapping("/exportjzdccktjb")
	@Operation(description = "救灾调出仓库统计表-导出excel", summary = "救灾调出仓库统计表-导出excel")
	public void exportjzdccktjb(@RequestBody OutboundInfoRequest outboundInfoRequest,
								HttpServletResponse response) {
		R<List<OutbountInfoResponse>> listR = selectDistributeListByWarehouse(outboundInfoRequest);

		String fileName = "exportjzdccktjb.xlsx";
		String templateFile = "救灾调出仓库统计表-导出模板.xlsx";
		try {
			outboundMaterialService.exportjzdccktjb(fileName,templateFile, listR.getData(),response);
		} catch (MyCustomException e) {
			throw new RuntimeException("导出失败");
		}
	}

	@PostMapping("/selectDistributeListByOutboundTime")
	@Operation(description = "查询出库下发明细(按调用批次)", summary = "查询出库下发明细(按调用批次)")
	@TranslationDict({
			@FieldParam(dictType = "province_ch", targetField = "province")
	})
	public R selectDistributeListByOutboundTime(@RequestBody OutboundInfoRequest outboundInfoRequest) {
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		outboundInfoRequest.setDeptIdList(deptIds);
		return outboundMaterialService.selectDistributeListByOutboundTime(outboundInfoRequest);
	}

	/**
	 * 救灾调用批次统计表-导出模板.xlsx
	 */
	@PostMapping("/exportjzdypctjb")
	@Operation(description = "救灾调用批次统计表-导出excel", summary = "救灾调用批次统计表-导出excel")
	public void exportjzdypctjb(@RequestBody OutboundInfoRequest outboundInfoRequest,
								HttpServletResponse response) {
		R<List<OutbountInfoResponse>> listR = selectDistributeListByOutboundTime(outboundInfoRequest);

		String fileName = "exportjzdypctjb.xlsx";
		String templateFile = "救灾调用批次统计表-导出模板.xlsx";
		try {
			outboundMaterialService.exportjzdypctjb(fileName,templateFile, listR.getData(),response);
		} catch (MyCustomException e) {
			throw new RuntimeException("导出失败");
		}
	}

	@Operation(summary = "导入出库(填报)", description = "导入出库(填报)")
	@PostMapping("/fill/import")
	public R importOutfill(@RequestExcel List<OutbountExcelVO> excelVOList, BindingResult bindingResult) {
		return outboundService.importOut(excelVOList, bindingResult,"5");
	}
	@Operation(summary = "导入出库(下发)", description = "导入出库(下发)")
	@PostMapping("/lower/import")
	public R importOutlower(@RequestExcel List<OutbountExcelVO> excelVOList, BindingResult bindingResult) {
		return outboundService.importOut(excelVOList, bindingResult,"7");
	}
	@Operation(summary = "导出出库模板", description = "导出出库模板")
	@GetMapping("/export")
	public void export(HttpServletResponse response) {
		try {
			EasyExcelUtil.createExcel(response,"出库模板",null,OutbountExcelVO.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
