package org.jeecg.modules.plan.controller;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.modules.device.entity.BuDevice;
import org.jeecg.modules.device.service.IBuDeviceService;
import org.jeecg.modules.plan.entity.Plan;
import org.jeecg.modules.plan.modal.PlanBo;
import org.jeecg.modules.plan.modal.DevicePlanVo;
import org.jeecg.modules.plan.service.IPlanService;

import lombok.extern.slf4j.Slf4j;

import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.modules.system.service.ISysDictService;
import org.jeecg.modules.workOrder.entity.WorkDivision;
import org.jeecg.modules.workOrder.mapper.WorkDivisionMapper;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.imports.ExcelImportServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;

 /**
 * @Description: 检修计划
 * @Author: jeecg-boot
 * @Date:   2025-01-16
 * @Version: V1.0
 */
@Api(tags="检修计划")
@RestController
@RequestMapping("/plan/plan")
@Slf4j
public class PlanController extends JeecgController<Plan, IPlanService> {
	@Autowired
	private IPlanService planService;
	@Autowired
	private WorkDivisionMapper workDivisionMapper;
	 @Autowired
	 private IBuDeviceService deviceService;
	 @Autowired
	 private ISysDictService dictService;

	/**
	 * 分页列表查询
	 *
	 * @param planBo
	 * @param req
	 * @return
	 */
	//@AutoLog(value = "检修计划-列表查询")
	@ApiOperation(value="检修计划-列表查询", notes="检修计划-列表查询")
	@GetMapping(value = "/list")
	public Result<List<Plan>> queryPageList(PlanBo planBo, HttpServletRequest req) {
		LambdaQueryWrapper<Plan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(StringUtils.isNoneBlank(planBo.getDeviceTypeId()), Plan::getDeviceId, planBo.getDeviceTypeId());
		queryWrapper.like(ObjectUtil.isNotNull(planBo.getCalMonth()), Plan::getCalDay, planBo.getCalMonth());
		if(StringUtils.isNotBlank(planBo.getCalMonthStart()) && StringUtils.isNotBlank(planBo.getCalMonthEnd())) {
			queryWrapper.between(Plan::getCalDay,planBo.getCalMonthStart(),planBo.getCalMonthEnd());
		}
		return Result.OK(planService.queryList(queryWrapper));
	}

	/**
	 *   添加
	 *
	 * @param plan
	 * @return
	 */
	@AutoLog(value = "检修计划-添加")
	@ApiOperation(value="检修计划-添加", notes="检修计划-添加")
	//@RequiresPermissions("org.jeecg.modules:bu_plan:add")
	@PostMapping(value = "/add")
	public Result<String> add(@RequestBody Plan plan) {
		try {
			planService.save(plan);
			return Result.OK("添加成功！");
		} catch (Exception e){
			return Result.error(e.getMessage());
		}
	}

	/**
	 *  编辑
	 *
	 * @param plan
	 * @return
	 */
	@AutoLog(value = "检修计划-编辑")
	@ApiOperation(value="检修计划-编辑", notes="检修计划-编辑")
	//@RequiresPermissions("org.jeecg.modules:bu_plan:edit")
	@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
	public Result<String> edit(@RequestBody Plan plan) {
		planService.updateById(plan);
		return Result.OK("编辑成功!");
	}

	/**
	 *   通过id删除
	 *
	 * @param id
	 * @return
	 */
	@AutoLog(value = "检修计划-通过id删除")
	@ApiOperation(value="检修计划-通过id删除", notes="检修计划-通过id删除")
	//@RequiresPermissions("org.jeecg.modules:bu_plan:delete")
	@DeleteMapping(value = "/delete")
	public Result<String> delete(@RequestParam(name="id",required=true) String id) {
		planService.removeById(id);
		return Result.OK("删除成功!");
	}

	/**
	 *  批量删除
	 *
	 * @param ids
	 * @return
	 */
	@AutoLog(value = "检修计划-批量删除")
	@ApiOperation(value="检修计划-批量删除", notes="检修计划-批量删除")
	//@RequiresPermissions("org.jeecg.modules:bu_plan:deleteBatch")
	@DeleteMapping(value = "/deleteBatch")
	public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
		this.planService.removeByIds(Arrays.asList(ids.split(",")));
		return Result.OK("批量删除成功!");
	}

	/**
	 * 通过id查询
	 *
	 * @param id
	 * @return
	 */
	//@AutoLog(value = "检修计划-通过id查询")
	@ApiOperation(value="检修计划-通过id查询", notes="检修计划-通过id查询")
	@GetMapping(value = "/queryById")
	public Result<Plan> queryById(@RequestParam(name="id",required=true) String id) {
		Plan plan = planService.getById(id);
		if(plan==null) {
			return Result.error("未找到对应数据");
		}
		return Result.OK(plan);
	}

    /**
    * 导出excel
    *
    * @param request
    * @param plan
    */
    //@RequiresPermissions("org.jeecg.modules:bu_plan:exportXls")
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, Plan plan) {
        return super.exportXls(request, plan, Plan.class, "检修计划");
    }

    /**
      * 通过excel导入数据
    *
    * @param request
    * @param response
    * @return
    */
    //@RequiresPermissions("bu_plan:importExcel")
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
		List<Plan> plans = new ArrayList<>();
		String[] weeks = {"日","一","二","三","四","五","六"};
		List<DictModel> repairRanges = dictService.getDictItems("repair_range");
		try{
			for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
				// 获取上传文件对象
				MultipartFile file = entity.getValue();
				ImportParams params = new ImportParams();
				params.setTitleRows(1);
				params.setHeadRows(2);
				params.setNeedSave(true);
				List<Map<String, Object>> result = (new ExcelImportServer()).importExcelByIs(file.getInputStream(), Map.class, params).getList();
				result.forEach(item -> {
					Map<String, Object> data = item.entrySet().stream().filter(entry -> entry.getValue()!=null)
							.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
					if(data.size() > 3){
						AtomicReference<String> deviceCode = new AtomicReference<>();
						AtomicReference<String> deviceName = new AtomicReference<>();
						List<Map<String, Object>> plansMap = new ArrayList<>();
						AtomicReference<LocalDate> planDate = new AtomicReference<>();
						AtomicReference<String> weekDay = new AtomicReference<>();
						AtomicReference<String> repairRange = new AtomicReference<>();
						data.entrySet().forEach(entry -> {
							String key = entry.getKey();
							Object rawValue = entry.getValue();

							// 安全转为字符串，避免 ClassCastException
							String value = "";
							if (rawValue != null) {
								if (rawValue instanceof Double) {
									Double d = (Double) rawValue;
									// 判断是否为整数（设备编号通常是整数）
									if (d % 1 == 0) {
										// 使用 BigDecimal 避免科学计数法
										value = new BigDecimal(d).toPlainString();
									} else {
										value = d.toString();
									}
								} else {
									value = rawValue.toString();
								}
							}

							switch (key){
								case "设备编号":
									deviceCode.set(value);
									break;
								case "设备名称":
									deviceName.set(value);
									break;
								case "日期_修程       星期":
									break;
								default:
									String[] temp = key.split("_");
									double excelDateValue = Double.parseDouble(temp[0]);
									Date date = DateUtil.getJavaDate(excelDateValue); // 默认使用 1900 基准
									LocalDate localDate = date.toInstant()
											.atZone(ZoneId.systemDefault())
											.toLocalDate();
									if(planDate.get()==null){
										Map<String, Object> plan = new HashMap<>();
										plan.put("planDate", localDate);
										plan.put("repairRange",value);
										plan.put("weekDay", temp[1]);
										plansMap.add(plan);
									}
							}
						});

//                        log.info("{},{},{},{},{}\n", deviceCode, deviceName, planDate.get().toString(), weekDay.get(), repairRange.get());
						BuDevice device = deviceService.getDeviceByCode(deviceCode.get());
						if(device!=null){
							plansMap.forEach(planMap -> {
								Plan plan = new Plan();
								//生成plan实体
								plan.setDeviceId(device.getId());
								plan.setCalDay((LocalDate) planMap.get("planDate"));
								plan.setCalWeek(ArrayUtil.indexOf(weeks, planMap.get("weekDay").toString()));
								String targetText = planMap.get("repairRange").toString();
								DictModel dictModel = repairRanges.stream()
										.filter(dict -> dict.getText().equals(targetText))
										.findFirst()
										.orElse(null);
								plan.setRapairRange(dictModel!=null?Integer.parseInt(dictModel.getValue()): -1);
								//去重
								long count = planService.count(new LambdaQueryWrapper<Plan>()
										.eq(Plan::getDeviceId, device.getId())
										.eq(Plan::getCalDay, plan.getCalDay())
										.eq(Plan::getRapairRange, plan.getRapairRange()));
								if(count <= 0)
									plans.add(plan);
							});
						}
					}
				});
				planService.saveBatch(plans);
			}
			return Result.OK();
		}catch (Exception e){
			return Result.error(e.getMessage());
		}

	}

	 /**
	  *  生成日计划
	  *
	  * @param plan
	  * @return
	  */
	 @AutoLog(value = "检修计划-生成日计划")
	 @ApiOperation(value="检修计划-生成日计划", notes="检修计划-生成日计划")
	 @PostMapping("/generate")
	 public Result<String> generate(@RequestBody PlanBo plan) {
		 try {
			 planService.generatePlan(plan);
			 return Result.OK("生成计划成功!");
		 }catch (Exception e) {
			 return Result.error(e.getMessage());
		 }
	 }

	 @AutoLog(value = "检修计划-查询检修规程列表")
	 @ApiOperation(value="检修计划-查询检修规程列表", notes="检修计划-查询检修规程列表")
	 @GetMapping("/queryrp")
	 public Result<List<DevicePlanVo>> getget() {
		 try {
			 return Result.OK(planService.queryRegularPlan());
		 }catch (Exception e) {
			 return Result.error(e.getMessage());
		 }
	 }

	 @AutoLog(value = "检修计划-查询检修规程列表")
	 @ApiOperation(value="检修计划-查询检修规程列表", notes="检修计划-查询检修规程列表")
	 @GetMapping("/devicePlan")
	 public Result<List<Plan>> devicePlan(@RequestParam(name="deviceId",required=true) String deviceId) {
		 try {
			 List<Plan> result = planService.list(new LambdaQueryWrapper<Plan>().eq(Plan::getDeviceId, deviceId));
			 result.forEach(plan -> {
				 WorkDivision workDivision = workDivisionMapper.selectOne(new LambdaQueryWrapper<WorkDivision>()
						 .eq(WorkDivision::getPlanId, plan.getId()).eq(WorkDivision::getTorType,0));
				 if(workDivision!=null) {
					 plan.setCoordinator(workDivision.getExecutor());
				 }
			 });
			 return Result.OK(result);
		 }catch (Exception e) {
			 return Result.error(e.getMessage());
		 }
	 }

	 @AutoLog("检修计划-检修日历拖拽修改计划日期")
	 @RequiresRoles({"admin"})
	 @PostMapping("/movePlan")
	 public Result<?> movePlan(@RequestBody Plan plan) {
		 planService.movePlan(plan);
		 return Result.ok("修改成功");
	 }

}
