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.api.vo.TreeNode;
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.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.annotation.Inner;
import com.emergency.avenue.common.security.util.SecurityUtils;
import com.emergency.avenue.storage.api.entity.InboundInfo;
import com.emergency.avenue.storage.api.entity.InboundMaterialInfo;
import com.emergency.avenue.storage.api.entity.InboundStatus;
import com.emergency.avenue.storage.api.request.InboundInfoRequest;
import com.emergency.avenue.storage.api.request.StorageMaterialsRequest;
import com.emergency.avenue.storage.api.response.InboundInfoResponse;
import com.emergency.avenue.storage.api.response.StorageMaterialsResponse;
import com.emergency.avenue.storage.api.vo.InbountExcelVO;
import com.emergency.avenue.storage.job.StockDataDockingJob;
import com.emergency.avenue.storage.service.InboundMaterialService;
import com.emergency.avenue.storage.service.InboundService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
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("/in")
@Tag(description = "inbound", name = "入库信息管理")
public class InboundInfoController {
	private final InboundService inboundService;

	private final InboundMaterialService inboundMaterialService;

	private final SysTreeDictService sysTreeDictService;

	private final SysDeptRelationService relationService;

	private final StockDataDockingJob inventoryDataDockingJob;

	@GetMapping("/page")
	@Operation(description = "入库分页查询", summary = "入库分页查询")
	public R<Page<InboundInfo>> getinboundPage(Page page, InboundInfo inboundInfo) {
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		QueryWrapper<InboundInfo> query = Wrappers.query(inboundInfo);
		query.lambda().in(InboundInfo::getDeptId,deptIds);
		String deptType = SecurityUtils.getUser().getDeptType();
		if (deptType.equals("2")) {
			query.lambda().ne(InboundInfo::getStatus,"1");
			query.orderByAsc("FIELD(status,'2','6','3','4','5')");
		}else if (deptType.equals("1")){
			query.lambda().notIn(InboundInfo::getStatus, Arrays.asList("1","2","4"));
			query.lambda().orderByAsc(InboundInfo::getStatus);
		}else if (deptType.equals("3")){
			query.orderByAsc("FIELD(status,'4','1','2','3','5','6')");
		}
		if (StringUtils.isNotEmpty(inboundInfo.getMaterialNameVo())) {
			QueryWrapper<SysTreeDict> queryWrapper = new QueryWrapper<>();
			queryWrapper.lambda().eq(SysTreeDict::getType,"1");
			queryWrapper.lambda().like(SysTreeDict::getName,inboundInfo.getMaterialNameVo());
			List<SysTreeDict> list1 = sysTreeDictService.list(queryWrapper);
			List<String> collect = list1.stream().map(SysTreeDict::getId).collect(Collectors.toList());
			if (collect.size()<1){
				return R.ok(page);
			}
			query.lambda().in(InboundInfo::getMaterialName,collect);
		}
		query.lambda().orderByDesc(InboundInfo::getSubmitTime);
		Page<InboundInfo> page1 = inboundService.page(page, query);
		List<SysTreeDict> list = sysTreeDictService.getList(1);
		Map<String, String> collect = list.stream().collect(Collectors.toMap(SysTreeDict::getId, SysTreeDict::getName));
		List<InboundInfo> records = page1.getRecords();
		for (InboundInfo inboundInfo1:records){
			inboundInfo1.setMaterialGroup(collect.get(inboundInfo1.getMaterialGroup()));
			inboundInfo1.setMaterialType(collect.get(inboundInfo1.getMaterialType()));
			inboundInfo1.setMaterialName(collect.get(inboundInfo1.getMaterialName()));
		}
		return R.ok(page1);
	}

	/**
	 * 通过ID查询入库信息
	 * @param id ID
	 * @return 入库信息
	 */
	@GetMapping("/{id}")
	@Operation(description = "通过ID查询入库信息", summary = "通过ID查询入库信息")
	public R<InboundInfo> getById(@PathVariable Integer id) {
		return R.ok(inboundService.getById(id));
	}


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


	@SysLog("添加入库信息")
	@PostMapping
	@Operation(description = "添加入库信息", summary = "添加入库信息")
	public R save(@RequestBody InboundInfo inboundInfo) {
		return inboundService.saveInbountAndMaterial(inboundInfo);
	}


	@SysLog("删除入库信息")
	@DeleteMapping("/{id}")
	@Operation(description = "删除入库信息", summary = "删除入库信息")
	public R removeById(@PathVariable Long id) {
		inboundMaterialService.remove(Wrappers.<InboundMaterialInfo>query().lambda().eq(InboundMaterialInfo::getInboundId, id));
		return R.ok(inboundService.removeById(id));
	}

	/**
	 * 修改入库信息
	 * @param inboundInfo 入库信息信息
	 * @return success/false
	 */
	@PutMapping
	@SysLog("修改入库信息")
	@Operation(description = "修改入库信息", summary = "修改入库信息")
	public R updateById(@RequestBody InboundInfo inboundInfo) {
		return R.ok(inboundService.updateInbountAndMaterial(inboundInfo));
	}

	@PutMapping("/auditing")
	@Operation(description = "审核入库信息", summary = "审核入库信息")
	public R auditing(@RequestBody InboundStatus inboundStatus) {
		return inboundMaterialService.saveInboundStatus(inboundStatus);
	}

	/**
	 * 查询入库明细
	 * @param inboundInfoRequest
	 * @return
	 */
	@PostMapping("/selectListByDept")
	@Operation(description = "查询入库明细", summary = "查询入库明细")
	public R<List<InboundInfoResponse>> selectListByDept(@RequestBody InboundInfoRequest inboundInfoRequest) {
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		inboundInfoRequest.setDeptIdList(deptIds);
		return inboundMaterialService.selectListByDept(inboundInfoRequest);
	}

	/**
	 * 查询库存明细-对外接口，对接库存信息
	 * @param secretKey 秘钥
	 * @return 库存明细信息
	 */
	@GetMapping("/getInventoryData")
	@Operation(description = "外部对接库存信息", summary = "外部对接库存信息")
	@Inner(value = false)
	public R getInventoryData() {
		inventoryDataDockingJob.executeDockStock1();
		return R.ok();
	}

	/**
	 * 查询库存明细-对外接口，对接库存信息
	 * @return 库存明细信息
	 */
	@GetMapping("/getInventoryData2")
	@Operation(description = "外部对接库存信息", summary = "外部对接库存信息")
	@Inner(value = false)
	public R getInventoryData2() {
		inventoryDataDockingJob.executeDockStock2();
		return R.ok();
	}

	/**
	 * 救灾物资明细统计表-导出模板.xlsx &
	 * 防汛抗旱明细统计表-导出（使用救灾相同模板）
	 */
	@PostMapping("/exportjzwzmxtjb")
	@Operation(description = "救灾物资明细统计表-导出excel", summary = "救灾物资明细统计表-导出excel")
	public void exportFxkhwzsljzb(@RequestBody InboundInfoRequest inboundInfoRequest,
								  HttpServletResponse response) {
		R<List<InboundInfoResponse>> listR = selectListByDept(inboundInfoRequest);
		String fileName = "exportjzwzmxtjb.xlsx";
		String templateFile = "救灾物资明细统计表-导出模板.xlsx";
		if (inboundInfoRequest.getIsMaintenance()){
			templateFile="维护保养救灾物资明细统计表-导出模板.xlsx";
		}
		try {
			 inboundMaterialService.exportFxkhwzsljzb(fileName,templateFile, listR.getData(),response);
		} catch (MyCustomException e) {
			throw new RuntimeException("导出失败");
		}
	}


	/**
	 * 查询入库明细 价格统计
	 * @param inboundInfoRequest
	 * @return
	 */
	@Operation(description = "查询入库明细 价格统计", summary = "查询入库明细 价格统计")
	@PostMapping("/selectListByDeptMoney")
	public R<List<InboundInfoResponse>> selectListByDeptMoney(@RequestBody InboundInfoRequest inboundInfoRequest) {
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		inboundInfoRequest.setDeptIdList(deptIds);
		return inboundMaterialService.selectListByDept(inboundInfoRequest);
	}


	@Operation(summary = "导入入库(填报)", description = "导入入库(填报)")
	@PostMapping("/fill/import")
	public R importInfill(@RequestExcel List<InbountExcelVO> excelVOList, BindingResult bindingResult) {
		return inboundService.importIn(excelVOList, bindingResult);
	}

	@Operation(summary = "导出入库库模板", description = "导出入库库模板")
	@GetMapping("/export")
	public void export(HttpServletResponse response) {
		try {
			EasyExcelUtil.createExcel(response,"入库模板",null, InbountExcelVO.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@PostMapping("/selectListByStorageMaterials")
	@Operation(description = "查询物资预警表", summary = "查询物资预警表")
	public R<List<StorageMaterialsResponse>> selectListByStorageMaterials(@RequestBody StorageMaterialsRequest storageMaterialsRequest) {
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		storageMaterialsRequest.setDeptIdList(deptIds);
		return inboundMaterialService.selectListByStorageMaterials(storageMaterialsRequest);
	}
	@GetMapping("/materials-tree")
	@Operation(description = "查询仓库的入库物资", summary = "查询仓库的入库物资")
	public R<List<TreeNode>> getMaterialsTreeByWarehouseId(@RequestParam String warehouseId) {
		return R.ok(inboundMaterialService.getMaterialsTreeByWarehouseId(warehouseId));
	}

}
